<commit_before>// (c) 2016 Joost Yervante Damad <joost@productize.be>

use std::fmt;
use std::path::PathBuf;

// from parent
use ERes;
use err;
use read_file;
use footprint;

extern crate rustysexp;
use self::rustysexp::Sexp;

pub struct Layout {
    pub version:i64,
    pub elements:Vec<Element>,
}

#[derive(Clone)]
pub enum Element {
    Module(footprint::Module),
    Net(Net),
    NetClass(NetClass),
    Other(Sexp),
}

#[derive(Clone,PartialEq)]
pub struct Net {
    pub num:i64,
    pub name:String,
}

#[derive(Clone,PartialEq)]
pub struct NetClass {
    pub name:String,
    pub desc:String,
    pub clearance:f64,
    pub trace_width:f64,
    pub via_dia:f64,
    pub via_drill:f64,
    pub uvia_dia:f64,
    pub uvia_drill:f64,
    pub nets:Vec<String>,
}

impl Layout {
    pub fn new() -> Layout {
        Layout {
            version:0,
            elements:vec![],
        }
    }

    pub fn insert_dummy_setup(&mut self) {
        self.elements.push(Element::Other(Sexp::List(vec![Sexp::String(String::from("setup"))])))
    }

    pub fn nets(&self) -> Vec<&Net> {
        let mut v = vec![];
        for element in &self.elements {
            match *element {
                Element::Net(ref net) => v.push(net),
                _ => (),
            }
        }
        v
    }

    pub fn netclasses(&self) -> Vec<&NetClass> {
        let mut v = vec![];
        for element in &self.elements {
            match *element {
                Element::NetClass(ref net_class) => v.push(net_class),
                _ => (),
            }
        }
        v
    }

    pub fn modify_module<F>(&mut self, reference:&String, fun:F) -> ERes<()>
        where F:Fn(&mut footprint::Module) -> ()
    {
        for ref mut x in &mut self.elements[..] {
            match **x {
                Element::Module(ref mut m) => {
                    if m.is_reference(reference) {
                        return Ok(fun(m))
                    }
                },
                Element::Net(_) => (),
                Element::NetClass(_) => (),
                Element::Other(_) => (),
            }
        }
        Err(format!("did not find module with reference {}", reference))
    }

    pub fn add_net(&mut self, num:i64, name:&'static str) {
        self.elements.push(Element::Net(Net { num:num, name:String::from(name) }));
    }
    pub fn add_netclass(&mut self, name:&'static str, desc:&'static str, clearance:f64, trace_width:f64, via_dia:f64, via_drill:f64, uvia_dia:f64, uvia_drill:f64, nets:Vec<String>) {
        self.elements.push(Element::NetClass(NetClass {
            name:String::from(name),
            desc:String::from(desc),
            clearance:clearance,
            trace_width:trace_width,
            via_dia:via_dia,
            via_drill:via_drill,
            uvia_dia:uvia_dia,
            uvia_drill:uvia_drill,
            nets:nets
            }));
    }

}

impl fmt::Display for Layout {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(writeln!(f, "(kicad_pcb (version {})", self.version));
        for element in &self.elements[..] {
            try!(writeln!(f, "  {}", element));
            try!(writeln!(f, ""));
        }
        writeln!(f, ")")
    }
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Other(ref s) => write!(f, "{}", s),
            Element::Module(ref s) => write!(f, "{}", s),
            Element::Net(ref s) => write!(f, "{}", s),
            Element::NetClass(ref s) => write!(f, "{}", s),
        }
    }
}

impl fmt::Display for Net {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.name.contains("(") || self.name.contains(")") || self.name.len()==0 {
            write!(f, "(net {} \"{}\")", self.num, self.name)
        } else {
            write!(f, "(net {} {})", self.num, self.name)
        }
    }
}
impl fmt::Display for NetClass {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(net_class {} \"{}\" ", self.name, self.desc));
        try!(write!(f, "(clearance {}) ", self.clearance));
        try!(write!(f, "(trace_width {}) ", self.trace_width));
        try!(write!(f, "(via_dia {}) ", self.via_dia));
        try!(write!(f, "(via_drill {}) ", self.via_drill));
        try!(write!(f, "(uvia_dia {}) ", self.uvia_dia));
        try!(write!(f, "(uvia_drill {}) ", self.uvia_drill));
        for net in &self.nets {
            if net.contains("(") || net.contains(")") {
                try!(write!(f, "(add_net \"{}\")", net))
            } else {
                try!(write!(f, "(add_net {})", net))
            }
        }
        write!(f, ")")

    }
}

fn parse_version(e:&Sexp) -> ERes<i64> {
    let l = try!(e.slice_atom("version"));
    l[0].i()
}

fn parse_other(e:&Sexp) -> Element {
    let e2 = e.clone();
    Element::Other(e2)
}

fn parse_module(e:&Sexp) -> ERes<Element> {
    let e2 = e.clone();
    let m = try!(footprint::parse_module(e2));
    Ok(Element::Module(m))
}

fn parse_net(e:&Sexp) -> ERes<Element> {
    let l = try!(e.slice_atom("net"));
    let num = try!(l[0].i());
    let name = try!(l[1].string()).clone();
    Ok(Element::Net(Net { name:name, num:num }))
}

fn parse_net_class(e:&Sexp) -> ERes<Element> {
    fn parse(e:&Sexp, name:&str) -> ERes<f64> {
        let l = try!(e.slice_atom(name));
        l[0].f()
    }
    let l = try!(e.slice_atom("net_class"));
    let name = try!(l[0].string()).clone();
    let desc = try!(l[1].string()).clone();
    let mut clearance = 0.1524;
    let mut trace_width = 0.2032;
    let mut via_dia = 0.675;
    let mut via_drill = 0.25;
    let mut uvia_dia = 0.508;
    let mut uvia_drill = 0.127;
    let mut nets = vec![];
    for x in &l[2..] {
        let list_name = try!(x.list_name());
        let xn = &list_name[..];
        match xn {
            "add_net" => {
                let l1 = try!(x.slice_atom("add_net"));
                nets.push(try!(l1[0].string()).clone())
            },
            "clearance" => clearance = try!(parse(x, xn)),
            "trace_width" => trace_width = try!(parse(x, xn)),
            "via_dia" => via_dia = try!(parse(x, xn)),
            "via_drill" => via_drill = try!(parse(x, xn)),
            "uvia_dia" => uvia_dia = try!(parse(x, xn)),
            "uvia_drill" => uvia_drill = try!(parse(x, xn)),
            _ => return Err(format!("unknown net_class field {}", list_name))
        }
    }
    let net_class = NetClass {
        name:name, desc:desc, clearance:clearance, via_dia:via_dia,
        via_drill:via_drill, uvia_dia:uvia_dia, uvia_drill:uvia_drill,
        nets:nets, trace_width:trace_width,
    };
    Ok(Element::NetClass(net_class))
}

fn parse(s: &str) -> ERes<Layout> {
    let exp = match rustysexp::parse_str(s) {
        Ok(s) => s,
        Err(x) => return Err(format!("ParseError: {}", x)),
    };
    let l1 = try!(exp.slice_atom("kicad_pcb"));
    let mut layout = Layout::new();

    for ref e in l1 {
        match &try!(e.list_name())[..] {
            "version" => layout.version = try!(parse_version(e)),
            "module" => layout.elements.push(try!(parse_module(e))),
            "net" => layout.elements.push(try!(parse_net(e))),
            "net_class" => layout.elements.push(try!(parse_net_class(e))),
            _ => layout.elements.push(parse_other(e)),
        }
    }
    Ok(layout)
}

pub fn parse_str(s: &str) -> ERes<Layout> {
    parse(s)
}

pub fn parse_file(filename: &PathBuf) -> ERes<Layout> {
    let name = filename.to_str().unwrap();
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => Err(format!("io error: {}", x))
    });
    parse(&s[..])
}
<commit_msg>add equal_no_net test<commit_after>// (c) 2016 Joost Yervante Damad <joost@productize.be>

use std::fmt;
use std::path::PathBuf;

// from parent
use ERes;
use err;
use read_file;
use footprint;

extern crate rustysexp;
use self::rustysexp::Sexp;

pub struct Layout {
    pub version:i64,
    pub elements:Vec<Element>,
}

#[derive(Clone)]
pub enum Element {
    Module(footprint::Module),
    Net(Net),
    NetClass(NetClass),
    Other(Sexp),
}

#[derive(Clone,PartialEq)]
pub struct Net {
    pub num:i64,
    pub name:String,
}

#[derive(Clone,PartialEq)]
pub struct NetClass {
    pub name:String,
    pub desc:String,
    pub clearance:f64,
    pub trace_width:f64,
    pub via_dia:f64,
    pub via_drill:f64,
    pub uvia_dia:f64,
    pub uvia_drill:f64,
    pub nets:Vec<String>,
}

impl Layout {
    pub fn new() -> Layout {
        Layout {
            version:0,
            elements:vec![],
        }
    }

    pub fn insert_dummy_setup(&mut self) {
        self.elements.push(Element::Other(Sexp::List(vec![Sexp::String(String::from("setup"))])))
    }

    pub fn nets(&self) -> Vec<&Net> {
        let mut v = vec![];
        for element in &self.elements {
            match *element {
                Element::Net(ref net) => v.push(net),
                _ => (),
            }
        }
        v
    }

    pub fn netclasses(&self) -> Vec<&NetClass> {
        let mut v = vec![];
        for element in &self.elements {
            match *element {
                Element::NetClass(ref net_class) => v.push(net_class),
                _ => (),
            }
        }
        v
    }

    pub fn modify_module<F>(&mut self, reference:&String, fun:F) -> ERes<()>
        where F:Fn(&mut footprint::Module) -> ()
    {
        for ref mut x in &mut self.elements[..] {
            match **x {
                Element::Module(ref mut m) => {
                    if m.is_reference(reference) {
                        return Ok(fun(m))
                    }
                },
                Element::Net(_) => (),
                Element::NetClass(_) => (),
                Element::Other(_) => (),
            }
        }
        Err(format!("did not find module with reference {}", reference))
    }

    pub fn add_net(&mut self, num:i64, name:&'static str) {
        self.elements.push(Element::Net(Net { num:num, name:String::from(name) }));
    }
    pub fn add_netclass(&mut self, name:&'static str, desc:&'static str, clearance:f64, trace_width:f64, via_dia:f64, via_drill:f64, uvia_dia:f64, uvia_drill:f64, nets:Vec<String>) {
        self.elements.push(Element::NetClass(NetClass {
            name:String::from(name),
            desc:String::from(desc),
            clearance:clearance,
            trace_width:trace_width,
            via_dia:via_dia,
            via_drill:via_drill,
            uvia_dia:uvia_dia,
            uvia_drill:uvia_drill,
            nets:nets
            }));
    }
}

impl NetClass {
    pub fn equal_no_net(&self, other:&NetClass) -> bool {
        let mut s1 = self.clone();
        s1.nets = vec![];
        let mut s2 = other.clone();
        s2.nets = vec![];
        return s1 == s2;
    }
}

impl fmt::Display for Layout {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(writeln!(f, "(kicad_pcb (version {})", self.version));
        for element in &self.elements[..] {
            try!(writeln!(f, "  {}", element));
            try!(writeln!(f, ""));
        }
        writeln!(f, ")")
    }
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Other(ref s) => write!(f, "{}", s),
            Element::Module(ref s) => write!(f, "{}", s),
            Element::Net(ref s) => write!(f, "{}", s),
            Element::NetClass(ref s) => write!(f, "{}", s),
        }
    }
}

impl fmt::Display for Net {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.name.contains("(") || self.name.contains(")") || self.name.len()==0 {
            write!(f, "(net {} \"{}\")", self.num, self.name)
        } else {
            write!(f, "(net {} {})", self.num, self.name)
        }
    }
}
impl fmt::Display for NetClass {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(net_class {} \"{}\" ", self.name, self.desc));
        try!(write!(f, "(clearance {}) ", self.clearance));
        try!(write!(f, "(trace_width {}) ", self.trace_width));
        try!(write!(f, "(via_dia {}) ", self.via_dia));
        try!(write!(f, "(via_drill {}) ", self.via_drill));
        try!(write!(f, "(uvia_dia {}) ", self.uvia_dia));
        try!(write!(f, "(uvia_drill {}) ", self.uvia_drill));
        for net in &self.nets {
            if net.contains("(") || net.contains(")") {
                try!(write!(f, "(add_net \"{}\")", net))
            } else {
                try!(write!(f, "(add_net {})", net))
            }
        }
        write!(f, ")")

    }
}

fn parse_version(e:&Sexp) -> ERes<i64> {
    let l = try!(e.slice_atom("version"));
    l[0].i()
}

fn parse_other(e:&Sexp) -> Element {
    let e2 = e.clone();
    Element::Other(e2)
}

fn parse_module(e:&Sexp) -> ERes<Element> {
    let e2 = e.clone();
    let m = try!(footprint::parse_module(e2));
    Ok(Element::Module(m))
}

fn parse_net(e:&Sexp) -> ERes<Element> {
    let l = try!(e.slice_atom("net"));
    let num = try!(l[0].i());
    let name = try!(l[1].string()).clone();
    Ok(Element::Net(Net { name:name, num:num }))
}

fn parse_net_class(e:&Sexp) -> ERes<Element> {
    fn parse(e:&Sexp, name:&str) -> ERes<f64> {
        let l = try!(e.slice_atom(name));
        l[0].f()
    }
    let l = try!(e.slice_atom("net_class"));
    let name = try!(l[0].string()).clone();
    let desc = try!(l[1].string()).clone();
    let mut clearance = 0.1524;
    let mut trace_width = 0.2032;
    let mut via_dia = 0.675;
    let mut via_drill = 0.25;
    let mut uvia_dia = 0.508;
    let mut uvia_drill = 0.127;
    let mut nets = vec![];
    for x in &l[2..] {
        let list_name = try!(x.list_name());
        let xn = &list_name[..];
        match xn {
            "add_net" => {
                let l1 = try!(x.slice_atom("add_net"));
                nets.push(try!(l1[0].string()).clone())
            },
            "clearance" => clearance = try!(parse(x, xn)),
            "trace_width" => trace_width = try!(parse(x, xn)),
            "via_dia" => via_dia = try!(parse(x, xn)),
            "via_drill" => via_drill = try!(parse(x, xn)),
            "uvia_dia" => uvia_dia = try!(parse(x, xn)),
            "uvia_drill" => uvia_drill = try!(parse(x, xn)),
            _ => return Err(format!("unknown net_class field {}", list_name))
        }
    }
    let net_class = NetClass {
        name:name, desc:desc, clearance:clearance, via_dia:via_dia,
        via_drill:via_drill, uvia_dia:uvia_dia, uvia_drill:uvia_drill,
        nets:nets, trace_width:trace_width,
    };
    Ok(Element::NetClass(net_class))
}

fn parse(s: &str) -> ERes<Layout> {
    let exp = match rustysexp::parse_str(s) {
        Ok(s) => s,
        Err(x) => return Err(format!("ParseError: {}", x)),
    };
    let l1 = try!(exp.slice_atom("kicad_pcb"));
    let mut layout = Layout::new();

    for ref e in l1 {
        match &try!(e.list_name())[..] {
            "version" => layout.version = try!(parse_version(e)),
            "module" => layout.elements.push(try!(parse_module(e))),
            "net" => layout.elements.push(try!(parse_net(e))),
            "net_class" => layout.elements.push(try!(parse_net_class(e))),
            _ => layout.elements.push(parse_other(e)),
        }
    }
    Ok(layout)
}

pub fn parse_str(s: &str) -> ERes<Layout> {
    parse(s)
}

pub fn parse_file(filename: &PathBuf) -> ERes<Layout> {
    let name = filename.to_str().unwrap();
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => Err(format!("io error: {}", x))
    });
    parse(&s[..])
}
<|endoftext|>


<commit_before>use super::swarm::Swarm;
use super::messaging::{Message, Actor, Individual, Packet, Recipient};
use super::inbox::Inbox;
use super::type_registry::TypeRegistry;
use std::intrinsics::{type_id, type_name};

/// The single, global actor system for the whole program
pub static mut THE_SYSTEM: *mut ActorSystem = 0 as *mut ActorSystem;

/// The ID used to specify a specific object within the actor system
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct ID {
    /// The sequentially numbered type ID of the actor within the actor system
    pub type_id: u16,
    /// The version of the game which the actor was created in
    pub version: u8,
    /// The instance of the type used to address a specific actor
    /// Is broadcast if equal to `u32::max_value()1`
    /// Is swarm if equal to `u32::max_value() -1`
    pub instance_id: u32
}

impl ID {
    /// Construct an invalid ID
    /// Uses similarly to a null pointer
    pub fn invalid() -> ID {ID {type_id: u16::max_value(), version: u8::max_value(), instance_id: 0}}

    /// Construct an individual actor ID with instance ID of 0 and the typeID specified
    pub fn individual(individual_type_id: usize) -> ID {
        ID {type_id: individual_type_id as u16, version: 0, instance_id: 0}
    }

    /// Construct a broadcast ID to all actors with the type ID specified
    pub fn broadcast(type_id: usize) -> ID {
        ID {type_id: type_id as u16, version: 0, instance_id: u32::max_value()}
    }

    /// Construct an individual actor ID
    pub fn instance(type_id: usize, instance_id_and_version: (usize, usize)) -> ID {
        ID {type_id: type_id as u16, version: instance_id_and_version.1 as u8, instance_id: instance_id_and_version.0 as u32}
    }

    /// Checks if ID is a broadcast ID
    pub fn is_broadcast(&self) -> bool {
        self.instance_id == u32::max_value()
    }

    /// Created swarm ID with type ID specified
    pub fn swarm(type_id: usize) -> ID {
        ID {type_id: type_id as u16, version: 0, instance_id: u32::max_value() - 1}
    }

    /// Checks if ID is a swarm ID
    pub fn is_swarm(&self) -> bool {
        self.instance_id == u32::max_value() - 1
    }
}

impl Default for ID {
    fn default() -> Self {
        ID::invalid()
    }
}

impl ::std::fmt::Debug for ID {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "ID {}_{}_{}", self.type_id, self.version, self.instance_id)
    }
}

impl<M: Message> ::std::ops::Shl<M> for ID {
    type Output = ();
    /// The shift left operator is overloaded to use to send messages
    /// e.g. recipient_ID << message
    fn shl(self, rhs: M) {
        unsafe {(*THE_SYSTEM).send(self, rhs);}
    }
}

const MAX_RECIPIENT_TYPES : usize = 64;
const MAX_MESSAGE_TYPES_PER_RECIPIENT: usize = 32;

#[derive(Clone)]
struct InboxMap {
    /// Amount of valid entries in the InboxMap
    length: usize,
    /// Entry consists of TypeID of Message type and pointer to inbox
    entries: [Option<(u64, *mut u8)>; MAX_MESSAGE_TYPES_PER_RECIPIENT]
}

impl InboxMap {
    /// Creates an empty InboxMap
    fn new() -> InboxMap {
        InboxMap{length: 0, entries: [None; MAX_MESSAGE_TYPES_PER_RECIPIENT]}
    }

    /// Adds new message type to the InboxMap
    fn add_new<M: Message>(&mut self, pointer: *mut Inbox<M>) {
        let message_type_id = unsafe{type_id::<M>()};
        let entry_is_for_id = |entry: &&Option<(u64, *mut u8)>| {
            entry.is_some() && entry.unwrap().0 == message_type_id
        };
        assert!(self.entries.iter().find(entry_is_for_id).is_none());
        self.entries[self.length] = Some((message_type_id, pointer as *mut u8));
        self.length += 1;
    }

    /// Gets the inbox pointer of the type specified if there is one
    fn get<M: Message>(&self) -> Option<*mut Inbox<M>> {
        let message_type_id = unsafe{type_id::<M>()};
        for entry in &self.entries {if let Some((id, pointer)) = *entry {
            if id == message_type_id {return Some(pointer as *mut Inbox<M>)}
        }}
        None
    }
}

pub struct ActorSystem {
    /// Stores the inboxes of all the swarms
    routing: [Option<InboxMap>; MAX_RECIPIENT_TYPES],
    /// Stores the rust TypeID to internal ID and type name mapping
    recipient_registry: TypeRegistry,
    /// Stores all swarms
    individuals: [Option<*mut u8>; MAX_RECIPIENT_TYPES],
    /// Closures to process and clear messages
    update_callbacks: Vec<Box<Fn()>>,
    /// Closures to clear messages
    clear_callbacks: Vec<Box<Fn()>>,
}

macro_rules! make_array {
    ($n:expr, $constructor:expr) => {{
        let mut items: [_; $n] = ::std::mem::uninitialized();
        for (i, place) in items.iter_mut().enumerate() {
            ::std::ptr::write(place, $constructor(i));
        }
        items
    }}
}

impl ActorSystem {
    /// Creates new actor system
    pub fn new() -> ActorSystem {
        ActorSystem {
            routing: unsafe{make_array!(MAX_RECIPIENT_TYPES, |_| None)},
            recipient_registry: TypeRegistry::new(),
            individuals: [None; MAX_RECIPIENT_TYPES],
            update_callbacks: Vec::new(),
            clear_callbacks: Vec::new()
        }
    }

    /// Registers a type for use as an actor in the actor system
    pub fn add_individual<I: Individual>(&mut self, individual: I) {
        // Register type in recipient_registry, and return the short ID of the type (sequential ID starting from 0)
        let recipient_id = self.recipient_registry.register_new::<I>();

        // Check inbox does not exist at routing[recipient_id]
        assert!(self.routing[recipient_id].is_none());

        self.routing[recipient_id] = Some(InboxMap::new());

        // Store pointer to the Swarm
        self.individuals[recipient_id] = Some(Box::into_raw(Box::new(individual)) as *mut u8);
    }

    /// Add a inbox for a given message type to a individual
    pub fn add_inbox<M: Message, I: Individual + Recipient<M>> (&mut self) {
        self.add_inbox_helper::<M, I>(true);
    }

    /// Add an unclearable inbox for a given message type to a individual
    pub fn add_unclearable_inbox<M: Message, I: Individual + Recipient<M>> (&mut self) {
        self.add_inbox_helper::<M, I>(false);
    }

    fn add_inbox_helper<M: Message, I: Individual + Recipient<M>> (&mut self, clearable: bool) {
        let inbox = Inbox::<M>::new();

        // Gets short ID of individual
        let recipient_id = self.recipient_registry.get::<I>();

        let inbox_ptr = self.store_inbox(inbox, recipient_id);
        let individual_ptr = self.individuals[recipient_id].unwrap() as *mut I;

        // Create closure to process messages
        self.update_callbacks.push(Box::new(move || {
            unsafe {
                for packet in (*inbox_ptr).empty() {
                    (*individual_ptr).receive_packet(packet);
                }
            }
        }));

        // Create closure to empty messages without processing
        if clearable {
            self.clear_callbacks.push(Box::new(move || {
                unsafe {
                    for _packet in (*inbox_ptr).empty() {
                    }
                }
            }));
        }
    }

    pub fn individual_id<I: Individual>(&mut self) -> ID {
        ID::individual(self.recipient_registry.get::<I>())
    }

    pub fn broadcast_id<A: Actor>(&mut self) -> ID {
        ID::broadcast(self.recipient_registry.get::<Swarm<A>>())
    }

    pub fn instance_id<A: Actor>(&mut self, instance_id_and_version: (usize, usize)) -> ID {
        ID::instance(self.recipient_registry.get::<Swarm<A>>(), instance_id_and_version)
    }

    /// Store the inbox pointer of a given type into the routing array
    fn store_inbox<M: Message>(&mut self, inbox: Inbox<M>, recipient_type_id: usize) -> *mut Inbox<M> {
        let inbox_ptr = Box::into_raw(Box::new(inbox));
        // TODO: deallocate inbox at the end of times
        self.routing[recipient_type_id].as_mut().unwrap().add_new(inbox_ptr);
        inbox_ptr
    }

    /// Get the inbox pointer of a given type from the routing array
    pub fn inbox_for<M: Message>(&mut self, packet: &Packet<M>) -> &mut Inbox<M> {
        if let Some(inbox_ptr) = self.routing[packet.recipient_id.type_id as usize].as_ref()
            .expect("Recipient not found")
            .get::<M>() {
                unsafe{&mut *inbox_ptr}
        } else {
            panic!("Inbox for {} not found for {}",
                unsafe{type_name::<M>()},
                self.recipient_registry.get_name(packet.recipient_id.type_id as usize))
        }
    }

    /// Places message into the inbox of a given type
    fn send<M: Message>(&mut self, recipient: ID, message: M) {
        let packet = Packet{
            recipient_id: recipient,
            message: message
        };
        self.inbox_for(&packet).put(packet);
    }

    /// Process all messages and clear all inboxes afterwards
    pub fn process_messages(&mut self) {
        for callback in &self.update_callbacks {
            callback();
        }
    }

    /// Clear all inboxes without processing
    pub fn clear_all_clearable_messages(&mut self) {
        for callback in &self.clear_callbacks {
            callback();
        }
    }

    /// Process messages, up to 1000 layers of recursion
    pub fn process_all_messages(&mut self) {
        for _i in 0..1000 {
            self.process_messages();
        }
    }
}

impl Default for ActorSystem {
    fn default() -> Self {
        Self::new()
    }
}<commit_msg>Fix typo, thanks @chances!<commit_after>use super::swarm::Swarm;
use super::messaging::{Message, Actor, Individual, Packet, Recipient};
use super::inbox::Inbox;
use super::type_registry::TypeRegistry;
use std::intrinsics::{type_id, type_name};

/// The single, global actor system for the whole program
pub static mut THE_SYSTEM: *mut ActorSystem = 0 as *mut ActorSystem;

/// The ID used to specify a specific object within the actor system
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct ID {
    /// The sequentially numbered type ID of the actor within the actor system
    pub type_id: u16,
    /// The version of the game which the actor was created in
    pub version: u8,
    /// The instance of the type used to address a specific actor
    /// Is broadcast if equal to `u32::max_value()1`
    /// Is swarm if equal to `u32::max_value() -1`
    pub instance_id: u32
}

impl ID {
    /// Construct an invalid ID
    /// Used similarly to a null pointer
    pub fn invalid() -> ID {ID {type_id: u16::max_value(), version: u8::max_value(), instance_id: 0}}

    /// Construct an individual actor ID with instance ID of 0 and the typeID specified
    pub fn individual(individual_type_id: usize) -> ID {
        ID {type_id: individual_type_id as u16, version: 0, instance_id: 0}
    }

    /// Construct a broadcast ID to all actors with the type ID specified
    pub fn broadcast(type_id: usize) -> ID {
        ID {type_id: type_id as u16, version: 0, instance_id: u32::max_value()}
    }

    /// Construct an individual actor ID
    pub fn instance(type_id: usize, instance_id_and_version: (usize, usize)) -> ID {
        ID {type_id: type_id as u16, version: instance_id_and_version.1 as u8, instance_id: instance_id_and_version.0 as u32}
    }

    /// Checks if ID is a broadcast ID
    pub fn is_broadcast(&self) -> bool {
        self.instance_id == u32::max_value()
    }

    /// Created swarm ID with type ID specified
    pub fn swarm(type_id: usize) -> ID {
        ID {type_id: type_id as u16, version: 0, instance_id: u32::max_value() - 1}
    }

    /// Checks if ID is a swarm ID
    pub fn is_swarm(&self) -> bool {
        self.instance_id == u32::max_value() - 1
    }
}

impl Default for ID {
    fn default() -> Self {
        ID::invalid()
    }
}

impl ::std::fmt::Debug for ID {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "ID {}_{}_{}", self.type_id, self.version, self.instance_id)
    }
}

impl<M: Message> ::std::ops::Shl<M> for ID {
    type Output = ();
    /// The shift left operator is overloaded to use to send messages
    /// e.g. recipient_ID << message
    fn shl(self, rhs: M) {
        unsafe {(*THE_SYSTEM).send(self, rhs);}
    }
}

const MAX_RECIPIENT_TYPES : usize = 64;
const MAX_MESSAGE_TYPES_PER_RECIPIENT: usize = 32;

#[derive(Clone)]
struct InboxMap {
    /// Amount of valid entries in the InboxMap
    length: usize,
    /// Entry consists of TypeID of Message type and pointer to inbox
    entries: [Option<(u64, *mut u8)>; MAX_MESSAGE_TYPES_PER_RECIPIENT]
}

impl InboxMap {
    /// Creates an empty InboxMap
    fn new() -> InboxMap {
        InboxMap{length: 0, entries: [None; MAX_MESSAGE_TYPES_PER_RECIPIENT]}
    }

    /// Adds new message type to the InboxMap
    fn add_new<M: Message>(&mut self, pointer: *mut Inbox<M>) {
        let message_type_id = unsafe{type_id::<M>()};
        let entry_is_for_id = |entry: &&Option<(u64, *mut u8)>| {
            entry.is_some() && entry.unwrap().0 == message_type_id
        };
        assert!(self.entries.iter().find(entry_is_for_id).is_none());
        self.entries[self.length] = Some((message_type_id, pointer as *mut u8));
        self.length += 1;
    }

    /// Gets the inbox pointer of the type specified if there is one
    fn get<M: Message>(&self) -> Option<*mut Inbox<M>> {
        let message_type_id = unsafe{type_id::<M>()};
        for entry in &self.entries {if let Some((id, pointer)) = *entry {
            if id == message_type_id {return Some(pointer as *mut Inbox<M>)}
        }}
        None
    }
}

pub struct ActorSystem {
    /// Stores the inboxes of all the swarms
    routing: [Option<InboxMap>; MAX_RECIPIENT_TYPES],
    /// Stores the rust TypeID to internal ID and type name mapping
    recipient_registry: TypeRegistry,
    /// Stores all swarms
    individuals: [Option<*mut u8>; MAX_RECIPIENT_TYPES],
    /// Closures to process and clear messages
    update_callbacks: Vec<Box<Fn()>>,
    /// Closures to clear messages
    clear_callbacks: Vec<Box<Fn()>>,
}

macro_rules! make_array {
    ($n:expr, $constructor:expr) => {{
        let mut items: [_; $n] = ::std::mem::uninitialized();
        for (i, place) in items.iter_mut().enumerate() {
            ::std::ptr::write(place, $constructor(i));
        }
        items
    }}
}

impl ActorSystem {
    /// Creates new actor system
    pub fn new() -> ActorSystem {
        ActorSystem {
            routing: unsafe{make_array!(MAX_RECIPIENT_TYPES, |_| None)},
            recipient_registry: TypeRegistry::new(),
            individuals: [None; MAX_RECIPIENT_TYPES],
            update_callbacks: Vec::new(),
            clear_callbacks: Vec::new()
        }
    }

    /// Registers a type for use as an actor in the actor system
    pub fn add_individual<I: Individual>(&mut self, individual: I) {
        // Register type in recipient_registry, and return the short ID of the type (sequential ID starting from 0)
        let recipient_id = self.recipient_registry.register_new::<I>();

        // Check inbox does not exist at routing[recipient_id]
        assert!(self.routing[recipient_id].is_none());

        self.routing[recipient_id] = Some(InboxMap::new());

        // Store pointer to the Swarm
        self.individuals[recipient_id] = Some(Box::into_raw(Box::new(individual)) as *mut u8);
    }

    /// Add a inbox for a given message type to a individual
    pub fn add_inbox<M: Message, I: Individual + Recipient<M>> (&mut self) {
        self.add_inbox_helper::<M, I>(true);
    }

    /// Add an unclearable inbox for a given message type to a individual
    pub fn add_unclearable_inbox<M: Message, I: Individual + Recipient<M>> (&mut self) {
        self.add_inbox_helper::<M, I>(false);
    }

    fn add_inbox_helper<M: Message, I: Individual + Recipient<M>> (&mut self, clearable: bool) {
        let inbox = Inbox::<M>::new();

        // Gets short ID of individual
        let recipient_id = self.recipient_registry.get::<I>();

        let inbox_ptr = self.store_inbox(inbox, recipient_id);
        let individual_ptr = self.individuals[recipient_id].unwrap() as *mut I;

        // Create closure to process messages
        self.update_callbacks.push(Box::new(move || {
            unsafe {
                for packet in (*inbox_ptr).empty() {
                    (*individual_ptr).receive_packet(packet);
                }
            }
        }));

        // Create closure to empty messages without processing
        if clearable {
            self.clear_callbacks.push(Box::new(move || {
                unsafe {
                    for _packet in (*inbox_ptr).empty() {
                    }
                }
            }));
        }
    }

    pub fn individual_id<I: Individual>(&mut self) -> ID {
        ID::individual(self.recipient_registry.get::<I>())
    }

    pub fn broadcast_id<A: Actor>(&mut self) -> ID {
        ID::broadcast(self.recipient_registry.get::<Swarm<A>>())
    }

    pub fn instance_id<A: Actor>(&mut self, instance_id_and_version: (usize, usize)) -> ID {
        ID::instance(self.recipient_registry.get::<Swarm<A>>(), instance_id_and_version)
    }

    /// Store the inbox pointer of a given type into the routing array
    fn store_inbox<M: Message>(&mut self, inbox: Inbox<M>, recipient_type_id: usize) -> *mut Inbox<M> {
        let inbox_ptr = Box::into_raw(Box::new(inbox));
        // TODO: deallocate inbox at the end of times
        self.routing[recipient_type_id].as_mut().unwrap().add_new(inbox_ptr);
        inbox_ptr
    }

    /// Get the inbox pointer of a given type from the routing array
    pub fn inbox_for<M: Message>(&mut self, packet: &Packet<M>) -> &mut Inbox<M> {
        if let Some(inbox_ptr) = self.routing[packet.recipient_id.type_id as usize].as_ref()
            .expect("Recipient not found")
            .get::<M>() {
                unsafe{&mut *inbox_ptr}
        } else {
            panic!("Inbox for {} not found for {}",
                unsafe{type_name::<M>()},
                self.recipient_registry.get_name(packet.recipient_id.type_id as usize))
        }
    }

    /// Places message into the inbox of a given type
    fn send<M: Message>(&mut self, recipient: ID, message: M) {
        let packet = Packet{
            recipient_id: recipient,
            message: message
        };
        self.inbox_for(&packet).put(packet);
    }

    /// Process all messages and clear all inboxes afterwards
    pub fn process_messages(&mut self) {
        for callback in &self.update_callbacks {
            callback();
        }
    }

    /// Clear all inboxes without processing
    pub fn clear_all_clearable_messages(&mut self) {
        for callback in &self.clear_callbacks {
            callback();
        }
    }

    /// Process messages, up to 1000 layers of recursion
    pub fn process_all_messages(&mut self) {
        for _i in 0..1000 {
            self.process_messages();
        }
    }
}

impl Default for ActorSystem {
    fn default() -> Self {
        Self::new()
    }
}<|endoftext|>


<commit_before>#[macro_use]
extern crate slog;

extern crate futures;
extern crate tokio_core;
extern crate tokio_io;
extern crate tokio_uds;

extern crate rdmcommon;

use std::io;

use rdmcommon::ipc;
use rdmcommon::util;

use futures::{Future, Stream, Sink};
use slog::Logger;
use tokio_core::reactor::{Core, Handle};
use tokio_io::AsyncRead;
use tokio_uds::UnixStream;

pub struct RdmGreeter {
    log: Logger,
    core: Core,
    receiver: Box<Stream<Item = ipc::IpcMessage, Error = ipc::IpcError>>,
    sender: Box<Sink<SinkItem = ipc::IpcMessage, SinkError = ipc::IpcError>>,
}

#[derive(Debug)]
pub enum RdmGreeterError {
    Ipc(ipc::IpcError),
    Io(io::Error),
    FailedHandshake
}

impl From<io::Error> for RdmGreeterError {
    fn from(err: io::Error) -> RdmGreeterError {
        RdmGreeterError::Io(err)
    }
}

impl From<ipc::IpcError> for RdmGreeterError {
    fn from(err: ipc::IpcError) -> RdmGreeterError {
        RdmGreeterError::Ipc(err)
    }
}

impl RdmGreeter {
    pub fn new<L : Into<Option<Logger>>>(logger: L) -> Result<RdmGreeter, RdmGreeterError> {
        let log = logger.into().unwrap_or(util::plain_logger());
        let mut core = Core::new()?;
        let handle = core.handle();
        // TODO: move this into private fn
        debug!(log, "[RdmGreeter::new] Connecting server socket");
        let sock = UnixStream::connect("/home/florian/tmp/sock", &handle)?;
        let (tx, rx) = sock.framed(ipc::IpcMessageCodec).split();

        debug!(log, "[RdmGreeter::new] Sending ClientHello");
        let tx = core.run(tx.send(ipc::IpcMessage::ClientHello))?;

        debug!(log, "[RdmGreeter::new] Reading server response");
        let (resp, rx) = core.run(rx.take(1).into_future().map_err(|(err, _)| err))?;
        debug!(log, "[RdmGreeter::new] Got server response"; "response" => ?resp);

        match resp {
            Some(ipc::IpcMessage::ServerHello) => Ok(RdmGreeter {
                                                        core: core,
                                                        receiver: Box::new(rx),
                                                        sender: Box::new(tx),
                                                        log: log,
                                                  }),
            _ => Err(RdmGreeterError::FailedHandshake)
        }
    }
}

impl Drop for RdmGreeter {
    fn drop(&mut self) {
        debug!(self.log, "[RdmGreeter::drop] Dropping RdmGreeter..");
    }
}<commit_msg>[libgreeter] Fix clippy warnings<commit_after>#[macro_use]
extern crate slog;

extern crate futures;
extern crate tokio_core;
extern crate tokio_io;
extern crate tokio_uds;

extern crate rdmcommon;

use std::io;

use rdmcommon::ipc;
use rdmcommon::util;

use futures::{Future, Stream, Sink};
use slog::Logger;
use tokio_core::reactor::{Core, Handle};
use tokio_io::AsyncRead;
use tokio_uds::UnixStream;

pub struct RdmGreeter {
    log: Logger,
    core: Core,
    receiver: Box<Stream<Item = ipc::IpcMessage, Error = ipc::IpcError>>,
    sender: Box<Sink<SinkItem = ipc::IpcMessage, SinkError = ipc::IpcError>>,
}

#[derive(Debug)]
pub enum RdmGreeterError {
    Ipc(ipc::IpcError),
    Io(io::Error),
    FailedHandshake
}

impl From<io::Error> for RdmGreeterError {
    fn from(err: io::Error) -> RdmGreeterError {
        RdmGreeterError::Io(err)
    }
}

impl From<ipc::IpcError> for RdmGreeterError {
    fn from(err: ipc::IpcError) -> RdmGreeterError {
        RdmGreeterError::Ipc(err)
    }
}

impl RdmGreeter {
    pub fn new<L : Into<Option<Logger>>>(logger: L) -> Result<RdmGreeter, RdmGreeterError> {
        let log = logger.into().unwrap_or_else(util::plain_logger);
        let mut core = Core::new()?;
        let handle = core.handle();
        // TODO: move this into private fn
        debug!(log, "[RdmGreeter::new] Connecting server socket");
        let sock = UnixStream::connect("/home/florian/tmp/sock", &handle)?;
        let (tx, rx) = sock.framed(ipc::IpcMessageCodec).split();

        debug!(log, "[RdmGreeter::new] Sending ClientHello");
        let tx = core.run(tx.send(ipc::IpcMessage::ClientHello))?;

        debug!(log, "[RdmGreeter::new] Reading server response");
        let (resp, rx) = core.run(rx.take(1).into_future().map_err(|(err, _)| err))?;
        debug!(log, "[RdmGreeter::new] Got server response"; "response" => ?resp);

        match resp {
            Some(ipc::IpcMessage::ServerHello) => Ok(RdmGreeter {
                                                        core: core,
                                                        receiver: Box::new(rx),
                                                        sender: Box::new(tx),
                                                        log: log,
                                                  }),
            _ => Err(RdmGreeterError::FailedHandshake)
        }
    }
}

impl Drop for RdmGreeter {
    fn drop(&mut self) {
        debug!(self.log, "[RdmGreeter::drop] Dropping RdmGreeter..");
    }
}<|endoftext|>


<commit_before>// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![cfg(target_os = "macos")]
use std::os::raw::c_char;
use std::slice;
use std::str;
use std::env;

use objc::runtime::{Class, Object};

pub fn set_locale_environment() {
    let (language_code, country_code) = unsafe {
        let locale_class = Class::get("NSLocale").unwrap();
        let locale: *const Object = msg_send![locale_class, currentLocale];
        msg_send![locale_class, release];
        let language_code: *const Object = msg_send![locale, languageCode];
        let country_code: *const Object = msg_send![locale, countryCode];
        msg_send![locale, release];
        let language_code_str = nsstring_as_str(language_code).to_owned();
        msg_send![language_code, release];
        let country_code_str = nsstring_as_str(country_code).to_owned();
        msg_send![country_code, release];
        (language_code_str, country_code_str)
    };
    let locale_id = format!("{}_{}.UTF-8", &language_code, &country_code);
    env::set_var("LANG", &locale_id);
}

const UTF8_ENCODING: usize = 4;

unsafe fn nsstring_as_str<'a>(nsstring: *const Object) -> &'a str {
    let cstr: *const c_char = msg_send![nsstring, UTF8String];
    let len: usize = msg_send![nsstring, lengthOfBytesUsingEncoding: UTF8_ENCODING];
    str::from_utf8(slice::from_raw_parts(cstr as *const u8, len)).unwrap()
}

#[cfg(not(target_os = "macos"))]
pub fn set_locale_environment() {}
<commit_msg>macos: add check for valid locale<commit_after>// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![cfg(target_os = "macos")]
use libc::{LC_CTYPE, setlocale};
use std::ffi::{CString, CStr};
use std::os::raw::c_char;
use std::ptr::null;
use std::slice;
use std::str;
use std::env;

use objc::runtime::{Class, Object};

pub fn set_locale_environment() {
    let (language_code, country_code) = unsafe {
        let locale_class = Class::get("NSLocale").unwrap();
        let locale: *const Object = msg_send![locale_class, currentLocale];
        msg_send![locale_class, release];
        let language_code: *const Object = msg_send![locale, languageCode];
        let country_code: *const Object = msg_send![locale, countryCode];
        msg_send![locale, release];
        let language_code_str = nsstring_as_str(language_code).to_owned();
        msg_send![language_code, release];
        let country_code_str = nsstring_as_str(country_code).to_owned();
        msg_send![country_code, release];
        (language_code_str, country_code_str)
    };
    let locale_id = format!("{}_{}.UTF-8", &language_code, &country_code);
    // check if locale_id is valid
    let locale_c_str = CString::new(locale_id.to_owned()).unwrap();
    let locale_ptr = locale_c_str.as_ptr();
    let locale_id = unsafe {
        // save a copy of original setting
        let original = setlocale(LC_CTYPE, null());
        let saved_original = if original.is_null() {
            CString::new("").unwrap()
        } else {
            CStr::from_ptr(original).to_owned()
        };
        // try setting `locale_id`
        let modified = setlocale(LC_CTYPE, locale_ptr);
        let result = if modified.is_null() {
            String::from("")
        } else {
            locale_id
        };
        // restore original setting
        setlocale(LC_CTYPE, saved_original.as_ptr());
        result
    };

    env::set_var("LANG", &locale_id);
}

const UTF8_ENCODING: usize = 4;

unsafe fn nsstring_as_str<'a>(nsstring: *const Object) -> &'a str {
    let cstr: *const c_char = msg_send![nsstring, UTF8String];
    let len: usize = msg_send![nsstring, lengthOfBytesUsingEncoding: UTF8_ENCODING];
    str::from_utf8(slice::from_raw_parts(cstr as *const u8, len)).unwrap()
}

#[cfg(not(target_os = "macos"))]
pub fn set_locale_environment() {}
<|endoftext|>


<commit_before>#[macro_export]
macro_rules! hsm_define_objects {
    ($st_str:ident, $st_en:ident, $st_evt:ty, ( $($s:ident),* ) ) => {
        _hsm_create_states!($($s),*);
        _hsm_create_state_enum!($st_en, ($($s),*));
        _hsm_create_state_struct!($st_str, $st_en, $st_evt, ($($s),*) );
    }
}

#[macro_export]
macro_rules! hsm_delayed_transition {
    ($probe:ident, $x:block) => {
        match $probe {
            true  => $crate::Action::DelayedTransition,
            false => $crate::Action::Transition($x)
        }
    }
}

#[macro_export]
macro_rules! hsm_impl_state {
    ($state:ident, $events:ident, $states:ident, $($pat:pat => $result:expr),*) => {
        impl $crate::State<$events, $states> for $state<$events, $states> {
            fn handle_event(&mut self, evt: $crate::Event<$events>, probe: bool) -> $crate::Action<$states> {
                match evt {
                    $( $pat => $result),*
                }
            }
        }
    }
}

#[macro_export]
macro_rules! _hsm_create_states {
    ( $($s:ident),* ) => {
        $(_hsm_create_state!($s);)*
    }
}

#[macro_export]
macro_rules! _hsm_create_state_common {
    ($nam:ident) => {
        impl<T, E> $crate::Name for $nam<T, E> {
            fn name(&self) -> &'static str {
                stringify!($nam)
            }
        }
        impl<T, E: Clone> $crate::Parent<E> for $nam<T, E> {
            fn get_parent(&self) -> Option<E> {
                self.parent.clone()
            }
            fn set_parent(&mut self, newparent: E) {
                self.parent = Some(newparent);
            }
        }
    }
}

#[macro_export]
macro_rules! _hsm_create_state {
    ($nam:ident) => {
        #[derive(Debug)]
        struct $nam<T, E> {
            _phantom_events: ::std::marker::PhantomData<T>,
            parent         : Option<E>
        }
        impl<T, E> $crate::Initializer for $nam<T, E> {
            fn new() -> Self {
                $nam {
                    _phantom_events: ::std::marker::PhantomData,
                    parent         : None
                }
            }
        }
        _hsm_create_state_common!($nam);
    };
    ($nam:ident, { $($field_name:ident: $field_type:ty: $field_default:expr),* }) => {
        #[derive(Debug)]
        struct $nam<T, E> {
            _phantom_events: ::std::marker::PhantomData<T>,
            parent         : Option<E>
            $( $field_name : $field_type ),*
        }
        impl<T, E> $crate::Initializer for $nam<T, E> {
            fn new() -> Self {
                $nam {
                    _phantom_events: ::std::marker::PhantomData,
                    parent         : None,
                    $( $field_name : $field_default ),*
                }
            }
        }
        _hsm_create_state_common!($nam);
    }
}

#[macro_export]
macro_rules! _hsm_create_state_enum {
    ($st_en:ident, ($($s:ident),*) ) => {
        #[derive(Debug, Clone, Eq, PartialEq)]
        enum $st_en {
            $( $s ),*
        }
        impl ::std::fmt::Display for $st_en {
            fn fmt(&self, f:&mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
                match *self {
                    $( $st_en::$s => try!(::std::fmt::Display::fmt(stringify!($s), f)) ),*
                };
                Ok(())
            }
        }
    }
}

#[macro_export]
macro_rules! _hsm_create_state_struct {
    ($st_str:ident, $st_en:ident, $st_evt:ty, ($($s:ident),*) ) => {
        #[derive(Debug)]
        #[allow(non_snake_case)]
        struct $st_str {
            $( $s : $s<$st_evt, $st_en> ),*
        }
        impl $crate::Initializer for $st_str {
            fn new() -> Self {
                $st_str {
                    $( $s : $s::new() ),*
                }
            }
        }
        impl $crate::StateLookup<$st_en, $st_evt> for $st_str {
            fn lookup(&mut self, typ: &$st_en) -> &mut $crate::State<$st_evt, $st_en> {
                match *typ {
                    $($st_en::$s => &mut self.$s ),*
                }
            }
        }
    }
}
<commit_msg>macros for states with internal variables<commit_after>#[macro_export]
macro_rules! hsm_define_objects {
    ($st_str:ident, $st_en:ident, $st_evt:ty, ( $($s:ident),* ) ) => {
        _hsm_create_states!($($s),*);
        _hsm_create_state_enum!($st_en, ($($s),*));
        _hsm_create_state_struct!($st_str, $st_en, $st_evt, ($($s),*) );
    };
    ($st_str:ident, $st_en:ident, $st_evt:ty, ( $($s:ident $x:tt),*)) => {
        _hsm_create_states!( $($s $x),* );
        _hsm_create_state_enum!($st_en, ($($s),*));
        _hsm_create_state_struct!($st_str, $st_en, $st_evt, ($($s),*) );
    }
}

#[macro_export]
macro_rules! hsm_delayed_transition {
    ($probe:ident, $x:block) => {
        match $probe {
            true  => $crate::Action::DelayedTransition,
            false => $crate::Action::Transition($x)
        }
    }
}

#[macro_export]
macro_rules! hsm_impl_state {
    ($state:ident, $events:ident, $states:ident, $($pat:pat => $result:expr),*) => {
        impl $crate::State<$events, $states> for $state<$events, $states> {
            fn handle_event(&mut self, evt: $crate::Event<$events>, probe: bool) -> $crate::Action<$states> {
                match evt {
                    $( $pat => $result),*
                }
            }
        }
    }
}

#[macro_export]
macro_rules! _hsm_create_states {
    ( $($s:ident),* ) => {
        $(_hsm_create_state!($s);)*
    };
    ($($s:ident $x:tt),*) => {
        $(_hsm_create_state!($s $x);)*
    }
}

#[macro_export]
macro_rules! _hsm_create_state_common {
    ($nam:ident) => {
        impl<T, E> $crate::Name for $nam<T, E> {
            fn name(&self) -> &'static str {
                stringify!($nam)
            }
        }
        impl<T, E: Clone> $crate::Parent<E> for $nam<T, E> {
            fn get_parent(&self) -> Option<E> {
                self.parent.clone()
            }
            fn set_parent(&mut self, newparent: E) {
                self.parent = Some(newparent);
            }
        }
    }
}

#[macro_export]
macro_rules! _hsm_create_state {
    ($nam:ident) => {
        #[derive(Debug)]
        struct $nam<T, E> {
            _phantom_events: ::std::marker::PhantomData<T>,
            parent         : Option<E>
        }
        impl<T, E> $crate::Initializer for $nam<T, E> {
            fn new() -> Self {
                $nam {
                    _phantom_events: ::std::marker::PhantomData,
                    parent         : None
                }
            }
        }
        _hsm_create_state_common!($nam);
    };
    ($nam:ident { $($field_name:ident : $field_type:ty = $field_default:expr),* }) => {
        #[derive(Debug)]
        struct $nam<T, E> {
            _phantom_events: ::std::marker::PhantomData<T>,
            parent         : Option<E>,
            $( $field_name : $field_type ),*
        }
        impl<T, E> $crate::Initializer for $nam<T, E> {
            fn new() -> Self {
                $nam {
                    _phantom_events: ::std::marker::PhantomData,
                    parent         : None,
                    $( $field_name : $field_default ),*
                }
            }
        }
        _hsm_create_state_common!($nam);
    }
}

#[macro_export]
macro_rules! _hsm_create_state_enum {
    ($st_en:ident, ($($s:ident),*) ) => {
        #[derive(Debug, Clone, Eq, PartialEq)]
        enum $st_en {
            $( $s ),*
        }
        impl ::std::fmt::Display for $st_en {
            fn fmt(&self, f:&mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
                match *self {
                    $( $st_en::$s => try!(::std::fmt::Display::fmt(stringify!($s), f)) ),*
                };
                Ok(())
            }
        }
    }
}

#[macro_export]
macro_rules! _hsm_create_state_struct {
    ($st_str:ident, $st_en:ident, $st_evt:ty, ($($s:ident),*) ) => {
        #[derive(Debug)]
        #[allow(non_snake_case)]
        struct $st_str {
            $( $s : $s<$st_evt, $st_en> ),*
        }
        impl $crate::Initializer for $st_str {
            fn new() -> Self {
                $st_str {
                    $( $s : $s::new() ),*
                }
            }
        }
        impl $crate::StateLookup<$st_en, $st_evt> for $st_str {
            fn lookup(&mut self, typ: &$st_en) -> &mut $crate::State<$st_evt, $st_en> {
                match *typ {
                    $($st_en::$s => &mut self.$s ),*
                }
            }
        }
    }
}
<|endoftext|>


<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
}<commit_msg>Macros for filling from markup<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(Box::new(unsafe {
    			let callback: $cbtyp = mem::transmute(*callback);
    			callback
    		})));
    	})+
	}
}<|endoftext|>


<commit_before>use std::net::TcpStream;
use std::collections::HashMap;
use std::io;
use std::io::{Read,Write};
use std::ops::Deref;
use libc;

use unix_socket::UnixStream;
use rustc_serialize::hex::ToHex;
use dbus_serialize::types::{Value,BasicValue};
use dbus_serialize::decoder::DBusDecoder;

use message;
use message::{Message,HeaderFieldName,MessageBuf};
use demarshal::{demarshal,DemarshalError};
use marshal::Marshal;

trait StreamSocket : Read + Write { }

impl StreamSocket for TcpStream { }
impl StreamSocket for UnixStream { }

enum Socket {
    Tcp(TcpStream),
    Uds(UnixStream)
}

pub struct Connection {
    sock: Socket,
    next_serial: u32,
    queue: Vec<Message>,
}

#[derive(Debug)]
pub enum Error {
    Disconnected,
    IOError(io::Error),
    DemarshalError(DemarshalError),
    BadData,
    AuthFailed,
}

impl From<io::Error> for Error {
    fn from(x: io::Error) -> Self {
        Error::IOError(x)
    }
}

impl From<DemarshalError> for Error {
    fn from(x: DemarshalError) -> Self {
        Error::DemarshalError(x)
    }
}

fn read_exactly(sock: &mut StreamSocket, buf: &mut Vec<u8>, len: usize) -> Result<(),Error> {
    buf.truncate(0);
    buf.reserve(len);
    if try!(sock.take(len as u64).read_to_end(buf)) != len {
        return Err(Error::Disconnected);
    }
    Ok(())
}

fn read_line(sock: &mut StreamSocket) -> Result<String,Error> {
    let mut line = "".to_string();
    let mut last = '\0';

    loop {
        let mut buf = vec![0];
        match sock.read(&mut buf) {
            Ok(x) if x > 0 => (),
            _ => return Err(Error::Disconnected)
        };
        let chr = buf[0] as char;
        line.push(chr);
        if chr == '\n' && last == '\r' {
            break;
        }
        last = chr;
    }
    Ok(line)
}

impl Connection {
    fn get_sock(&mut self) -> &mut StreamSocket {
        match self.sock {
            Socket::Tcp(ref mut x) => x,
            Socket::Uds(ref mut x) => x
        }
    }

    fn send_nul_byte(&mut self) -> Result<(),Error> {
        // Send NUL byte
        let sock = self.get_sock();
        let buf = vec![0];
        try!(sock.write_all(&buf));
        Ok(())
    }

    fn auth_anonymous(&mut self) -> Result<(),Error> {
        let sock = self.get_sock();

        try!(sock.write_all(b"AUTH ANONYMOUS 6c69626462757320312e382e3132\r\n"));

        // Read response
        let resp = try!(read_line(sock));
        if !resp.starts_with("OK ") {
            return Err(Error::AuthFailed);
        }

        // Ready for action
        try!(sock.write_all(b"BEGIN\r\n"));
        Ok(())
    }

    fn auth_external(&mut self) -> Result<(),Error> {
        let sock = self.get_sock();

        let uid = unsafe {
            libc::funcs::posix88::unistd::getuid()
        };
        let uid_str = uid.to_string();
        let uid_hex = uid_str.into_bytes().to_hex();
        let cmd = "AUTH EXTERNAL ".to_string() + &uid_hex + "\r\n";
        try!(sock.write_all(&cmd.into_bytes()));

        // Read response
        let resp = try!(read_line(sock));
        if !resp.starts_with("OK ") {
            return Err(Error::AuthFailed);
        }

        // Ready for action
        try!(sock.write_all(b"BEGIN\r\n"));
        Ok(())
    }

    fn say_hello(&mut self) -> Result<(String),Error> {
        let mut msg = message::create_method_call("org.freedesktop.DBus",
                                                  "/org/freedesktop/DBus",
                                                  "org.freedesktop.DBus",
                                                  "Hello");
        match try!(self.call_sync(&mut msg)).get(0) {
            Some(&Value::BasicValue(BasicValue::String(ref x))) => Ok(x.to_string()),
            _ => Err(Error::BadData)
        }
    }

    pub fn connect_uds(addr: &str) -> Result<Connection,Error> {
        let sock = try!(UnixStream::connect(addr));
        let mut conn = Connection {
            sock: Socket::Uds(sock),
            queue: Vec::new(),
            next_serial: 1
        };

        try!(conn.send_nul_byte());
        try!(conn.auth_external());
        try!(conn.say_hello());
        Ok(conn)
    }

    pub fn connect_tcp(addr: &str) -> Result<Connection,Error> {
        let sock = try!(TcpStream::connect(addr));
        let mut conn = Connection {
            sock: Socket::Tcp(sock),
            queue: Vec::new(),
            next_serial: 1
        };

        try!(conn.send_nul_byte());
        try!(conn.auth_anonymous());
        try!(conn.say_hello());
        Ok(conn)
    }

    pub fn send(&mut self, mbuf: &mut MessageBuf) -> Result<u32, Error> {
        let mut msg = &mut mbuf.0;
        // A minimum header with no body is 16 bytes
        let mut len = msg.len() as u32;
        if len < 16 {
            return Err(Error::BadData);
        }

        // Get the current length from the message, which only include the length of the header.
        // That field should actually be the length of only the body, so update that now
        let old_len = message::get_length(msg);
        len -= old_len;
        let mut buf = Vec::new();
        len.dbus_encode(&mut buf);
        // Update the message with a correct serial number, as well
        let this_serial = self.next_serial;
        self.next_serial += 1;
        this_serial.dbus_encode(&mut buf);
        message::set_length(msg, &buf);

        let sock = self.get_sock();
        try!(sock.write_all(msg));
        Ok(this_serial)
    }

    pub fn call_sync(&mut self, mbuf: &mut MessageBuf) -> Result<Vec<Value>,Error> {
        // XXX: assert that this is a method call with reply
        let serial = try!(self.send(mbuf));
        // We need a local queue so that read_msg doesn't just give us
        // the same one over and over
        let mut queue = Vec::new();
        loop {
            let mut msg = try!(self.read_msg());
            match msg.headers.remove(&(HeaderFieldName::ReplySerial as u8)) {
                Some(Value::Variant(x)) => {
                    let obj : Value = *x.object;
                    let reply_serial : u32 = DBusDecoder::decode(obj).unwrap();
                    if reply_serial == serial {
                        // Move our queued messages into the Connection's queue
                        for _ in 0..queue.len() {
                            self.queue.push(queue.remove(0));
                        }
                        return Ok(msg.body);
                    }
                }
                _ => ()
            };
            queue.push(msg);
        }
    }

    pub fn read_msg(&mut self) -> Result<Message,Error> {
        match self.queue.get(0) {
            Some(_) => return Ok(self.queue.remove(0)),
            _ => ()
        };
        let mut buf = Vec::new();
        let sock = self.get_sock();

        // Read and demarshal the fixed portion of the header
        try!(read_exactly(sock, &mut buf, 12));
        let mut offset = 0;
        let mut sig = "(yyyyuu)".to_string();
        let header = match try!(demarshal(&mut buf, &mut offset, &mut sig)) {
            Value::Struct(x) => x,
            x => panic!("Demarshal didn't return what we asked for: {:?}", x)
        };

        let mut v = header.objects;
        let mut msg : Message = Default::default();
        let endian : u8 = DBusDecoder::decode(v.remove(0)).unwrap();
        if endian == 'B' as u8 {
            msg.big_endian = true;
        }
        msg.message_type = message::MessageType(DBusDecoder::decode(v.remove(0)).unwrap());
        msg.flags = DBusDecoder::decode::<u8>(v.remove(0)).unwrap();
        msg.version = DBusDecoder::decode::<u8>(v.remove(0)).unwrap();
        let body_len = DBusDecoder::decode::<u32>(v.remove(0)).unwrap();
        msg.serial = DBusDecoder::decode::<u32>(v.remove(0)).unwrap();

        // Read array length
        try!(read_exactly(sock, &mut buf, 4));
        // demarshal consumes the buf, so save a copy for when we demarshal the entire array
        let mut buf_copy = buf.clone();
        offset = 12;
        sig = "u".to_string();
        let data = demarshal(&mut buf, &mut offset, &mut sig).ok().unwrap();
        let arr_len = DBusDecoder::decode::<u32>(data).unwrap() as usize;

        // Make buf_copy big enough for the entire array, and fill it
        buf_copy.reserve(arr_len);
        if try!(sock.take(arr_len as u64).read_to_end(&mut buf_copy)) != arr_len {
            return Err(Error::Disconnected);
        };

        offset = 12;
        sig = "a(yv)".to_string();
        let header_fields = match try!(demarshal(&mut buf_copy, &mut offset, &mut sig)) {
            Value::Array(x) => x,
            x => panic!("Demarshal didn't return what we asked for: {:?}", x)
        };

        msg.headers = HashMap::new();
        for i in header_fields.objects {
            let mut st = match i {
                Value::Struct(x) => x,
                x => panic!("Demarshal didn't return what we asked for: {:?}", x)
            };
            let val = st.objects.remove(1);
            let code = DBusDecoder::decode::<u8>(st.objects.remove(0)).unwrap();
            msg.headers.insert(code, val);
        }

        // Read the padding, if any
        let trailing_pad = 8 - (offset % 8);
        if trailing_pad % 8 != 0 {
            try!(read_exactly(sock, &mut buf, trailing_pad));
        }

        // Finally, read the entire body
        if body_len > 0 {
            let v = match msg.headers.get(&(HeaderFieldName::Signature as u8)) {
                Some(&Value::Variant(ref x)) => x,
                _ => return Err(Error::DemarshalError(DemarshalError::BadSignature))
            };

            let sigval = match v.object.deref() {
                &Value::BasicValue(BasicValue::Signature(ref x)) => x,
                _ => return Err(Error::DemarshalError(DemarshalError::BadSignature))
            };

            let mut body = Vec::new();
            try!(read_exactly(sock, &mut body, body_len as usize));

            let mut sig = "(".to_string() + &sigval.0 + ")";
            offset = 0;
            let objs = match try!(demarshal(&mut body, &mut offset, &mut sig)) {
                Value::Struct(x) => x.objects,
                x => panic!("Didn't get a struct: {:?}", x)
            };
            for x in objs {
                msg.body.push(x);
            }
        }

        Ok(msg)
    }
}

#[test]
fn test_connect () {
    let mut conn = Connection::connect_uds("/var/run/dbus/system_bus_socket").unwrap();
    let mut msg = message::create_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus",
                                          "org.freedesktop.DBus", "ListNames");
    let resp = conn.call_sync(&mut msg).unwrap();
    println!("ListNames: {:?}", resp);
}

#[cfg(tcp)]
#[test]
fn test_tcp () {
    let mut conn = Connection::connect_tcp("localhost:12345").unwrap();
    let mut msg = message::create_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus",
                                          "org.freedesktop.DBus", "ListNames");
    conn.send(&mut msg).ok();
    let msg = conn.read_msg().unwrap();
    println!("{:?}", msg.body);
    //loop {
    //    conn.read_msg().unwrap();
    //}
}
<commit_msg>connection.rs: disable tests that require running dbus-daemon<commit_after>use std::net::TcpStream;
use std::collections::HashMap;
use std::io;
use std::io::{Read,Write};
use std::ops::Deref;
use libc;

use unix_socket::UnixStream;
use rustc_serialize::hex::ToHex;
use dbus_serialize::types::{Value,BasicValue};
use dbus_serialize::decoder::DBusDecoder;

use message;
use message::{Message,HeaderFieldName,MessageBuf};
use demarshal::{demarshal,DemarshalError};
use marshal::Marshal;

trait StreamSocket : Read + Write { }

impl StreamSocket for TcpStream { }
impl StreamSocket for UnixStream { }

enum Socket {
    Tcp(TcpStream),
    Uds(UnixStream)
}

pub struct Connection {
    sock: Socket,
    next_serial: u32,
    queue: Vec<Message>,
}

#[derive(Debug)]
pub enum Error {
    Disconnected,
    IOError(io::Error),
    DemarshalError(DemarshalError),
    BadData,
    AuthFailed,
}

impl From<io::Error> for Error {
    fn from(x: io::Error) -> Self {
        Error::IOError(x)
    }
}

impl From<DemarshalError> for Error {
    fn from(x: DemarshalError) -> Self {
        Error::DemarshalError(x)
    }
}

fn read_exactly(sock: &mut StreamSocket, buf: &mut Vec<u8>, len: usize) -> Result<(),Error> {
    buf.truncate(0);
    buf.reserve(len);
    if try!(sock.take(len as u64).read_to_end(buf)) != len {
        return Err(Error::Disconnected);
    }
    Ok(())
}

fn read_line(sock: &mut StreamSocket) -> Result<String,Error> {
    let mut line = "".to_string();
    let mut last = '\0';

    loop {
        let mut buf = vec![0];
        match sock.read(&mut buf) {
            Ok(x) if x > 0 => (),
            _ => return Err(Error::Disconnected)
        };
        let chr = buf[0] as char;
        line.push(chr);
        if chr == '\n' && last == '\r' {
            break;
        }
        last = chr;
    }
    Ok(line)
}

impl Connection {
    fn get_sock(&mut self) -> &mut StreamSocket {
        match self.sock {
            Socket::Tcp(ref mut x) => x,
            Socket::Uds(ref mut x) => x
        }
    }

    fn send_nul_byte(&mut self) -> Result<(),Error> {
        // Send NUL byte
        let sock = self.get_sock();
        let buf = vec![0];
        try!(sock.write_all(&buf));
        Ok(())
    }

    fn auth_anonymous(&mut self) -> Result<(),Error> {
        let sock = self.get_sock();

        try!(sock.write_all(b"AUTH ANONYMOUS 6c69626462757320312e382e3132\r\n"));

        // Read response
        let resp = try!(read_line(sock));
        if !resp.starts_with("OK ") {
            return Err(Error::AuthFailed);
        }

        // Ready for action
        try!(sock.write_all(b"BEGIN\r\n"));
        Ok(())
    }

    fn auth_external(&mut self) -> Result<(),Error> {
        let sock = self.get_sock();

        let uid = unsafe {
            libc::funcs::posix88::unistd::getuid()
        };
        let uid_str = uid.to_string();
        let uid_hex = uid_str.into_bytes().to_hex();
        let cmd = "AUTH EXTERNAL ".to_string() + &uid_hex + "\r\n";
        try!(sock.write_all(&cmd.into_bytes()));

        // Read response
        let resp = try!(read_line(sock));
        if !resp.starts_with("OK ") {
            return Err(Error::AuthFailed);
        }

        // Ready for action
        try!(sock.write_all(b"BEGIN\r\n"));
        Ok(())
    }

    fn say_hello(&mut self) -> Result<(String),Error> {
        let mut msg = message::create_method_call("org.freedesktop.DBus",
                                                  "/org/freedesktop/DBus",
                                                  "org.freedesktop.DBus",
                                                  "Hello");
        match try!(self.call_sync(&mut msg)).get(0) {
            Some(&Value::BasicValue(BasicValue::String(ref x))) => Ok(x.to_string()),
            _ => Err(Error::BadData)
        }
    }

    pub fn connect_uds(addr: &str) -> Result<Connection,Error> {
        let sock = try!(UnixStream::connect(addr));
        let mut conn = Connection {
            sock: Socket::Uds(sock),
            queue: Vec::new(),
            next_serial: 1
        };

        try!(conn.send_nul_byte());
        try!(conn.auth_external());
        try!(conn.say_hello());
        Ok(conn)
    }

    pub fn connect_tcp(addr: &str) -> Result<Connection,Error> {
        let sock = try!(TcpStream::connect(addr));
        let mut conn = Connection {
            sock: Socket::Tcp(sock),
            queue: Vec::new(),
            next_serial: 1
        };

        try!(conn.send_nul_byte());
        try!(conn.auth_anonymous());
        try!(conn.say_hello());
        Ok(conn)
    }

    pub fn send(&mut self, mbuf: &mut MessageBuf) -> Result<u32, Error> {
        let mut msg = &mut mbuf.0;
        // A minimum header with no body is 16 bytes
        let mut len = msg.len() as u32;
        if len < 16 {
            return Err(Error::BadData);
        }

        // Get the current length from the message, which only include the length of the header.
        // That field should actually be the length of only the body, so update that now
        let old_len = message::get_length(msg);
        len -= old_len;
        let mut buf = Vec::new();
        len.dbus_encode(&mut buf);
        // Update the message with a correct serial number, as well
        let this_serial = self.next_serial;
        self.next_serial += 1;
        this_serial.dbus_encode(&mut buf);
        message::set_length(msg, &buf);

        let sock = self.get_sock();
        try!(sock.write_all(msg));
        Ok(this_serial)
    }

    pub fn call_sync(&mut self, mbuf: &mut MessageBuf) -> Result<Vec<Value>,Error> {
        // XXX: assert that this is a method call with reply
        let serial = try!(self.send(mbuf));
        // We need a local queue so that read_msg doesn't just give us
        // the same one over and over
        let mut queue = Vec::new();
        loop {
            let mut msg = try!(self.read_msg());
            match msg.headers.remove(&(HeaderFieldName::ReplySerial as u8)) {
                Some(Value::Variant(x)) => {
                    let obj : Value = *x.object;
                    let reply_serial : u32 = DBusDecoder::decode(obj).unwrap();
                    if reply_serial == serial {
                        // Move our queued messages into the Connection's queue
                        for _ in 0..queue.len() {
                            self.queue.push(queue.remove(0));
                        }
                        return Ok(msg.body);
                    }
                }
                _ => ()
            };
            queue.push(msg);
        }
    }

    pub fn read_msg(&mut self) -> Result<Message,Error> {
        match self.queue.get(0) {
            Some(_) => return Ok(self.queue.remove(0)),
            _ => ()
        };
        let mut buf = Vec::new();
        let sock = self.get_sock();

        // Read and demarshal the fixed portion of the header
        try!(read_exactly(sock, &mut buf, 12));
        let mut offset = 0;
        let mut sig = "(yyyyuu)".to_string();
        let header = match try!(demarshal(&mut buf, &mut offset, &mut sig)) {
            Value::Struct(x) => x,
            x => panic!("Demarshal didn't return what we asked for: {:?}", x)
        };

        let mut v = header.objects;
        let mut msg : Message = Default::default();
        let endian : u8 = DBusDecoder::decode(v.remove(0)).unwrap();
        if endian == 'B' as u8 {
            msg.big_endian = true;
        }
        msg.message_type = message::MessageType(DBusDecoder::decode(v.remove(0)).unwrap());
        msg.flags = DBusDecoder::decode::<u8>(v.remove(0)).unwrap();
        msg.version = DBusDecoder::decode::<u8>(v.remove(0)).unwrap();
        let body_len = DBusDecoder::decode::<u32>(v.remove(0)).unwrap();
        msg.serial = DBusDecoder::decode::<u32>(v.remove(0)).unwrap();

        // Read array length
        try!(read_exactly(sock, &mut buf, 4));
        // demarshal consumes the buf, so save a copy for when we demarshal the entire array
        let mut buf_copy = buf.clone();
        offset = 12;
        sig = "u".to_string();
        let data = demarshal(&mut buf, &mut offset, &mut sig).ok().unwrap();
        let arr_len = DBusDecoder::decode::<u32>(data).unwrap() as usize;

        // Make buf_copy big enough for the entire array, and fill it
        buf_copy.reserve(arr_len);
        if try!(sock.take(arr_len as u64).read_to_end(&mut buf_copy)) != arr_len {
            return Err(Error::Disconnected);
        };

        offset = 12;
        sig = "a(yv)".to_string();
        let header_fields = match try!(demarshal(&mut buf_copy, &mut offset, &mut sig)) {
            Value::Array(x) => x,
            x => panic!("Demarshal didn't return what we asked for: {:?}", x)
        };

        msg.headers = HashMap::new();
        for i in header_fields.objects {
            let mut st = match i {
                Value::Struct(x) => x,
                x => panic!("Demarshal didn't return what we asked for: {:?}", x)
            };
            let val = st.objects.remove(1);
            let code = DBusDecoder::decode::<u8>(st.objects.remove(0)).unwrap();
            msg.headers.insert(code, val);
        }

        // Read the padding, if any
        let trailing_pad = 8 - (offset % 8);
        if trailing_pad % 8 != 0 {
            try!(read_exactly(sock, &mut buf, trailing_pad));
        }

        // Finally, read the entire body
        if body_len > 0 {
            let v = match msg.headers.get(&(HeaderFieldName::Signature as u8)) {
                Some(&Value::Variant(ref x)) => x,
                _ => return Err(Error::DemarshalError(DemarshalError::BadSignature))
            };

            let sigval = match v.object.deref() {
                &Value::BasicValue(BasicValue::Signature(ref x)) => x,
                _ => return Err(Error::DemarshalError(DemarshalError::BadSignature))
            };

            let mut body = Vec::new();
            try!(read_exactly(sock, &mut body, body_len as usize));

            let mut sig = "(".to_string() + &sigval.0 + ")";
            offset = 0;
            let objs = match try!(demarshal(&mut body, &mut offset, &mut sig)) {
                Value::Struct(x) => x.objects,
                x => panic!("Didn't get a struct: {:?}", x)
            };
            for x in objs {
                msg.body.push(x);
            }
        }

        Ok(msg)
    }
}

#[cfg(dbus)]
#[test]
fn test_connect () {
    let mut conn = Connection::connect_uds("/var/run/dbus/system_bus_socket").unwrap();
    let mut msg = message::create_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus",
                                          "org.freedesktop.DBus", "ListNames");
    let resp = conn.call_sync(&mut msg).unwrap();
    println!("ListNames: {:?}", resp);
}

#[cfg(dbus)]
#[test]
fn test_tcp () {
    let mut conn = Connection::connect_tcp("localhost:12345").unwrap();
    let mut msg = message::create_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus",
                                          "org.freedesktop.DBus", "ListNames");
    conn.send(&mut msg).ok();
    let msg = conn.read_msg().unwrap();
    println!("{:?}", msg.body);
    //loop {
    //    conn.read_msg().unwrap();
    //}
}
<|endoftext|>