// Interfaces are mapped to traits.
Interfaces are mapped to traits.
Interfaces are mapped to traits .
pub fn generate_interface<'a, W: Write>(
        &self,
        interface: &Interface,
        sink: &'a mut W,
    ) -> Result<()> {
        writeln!(sink, "// Annotation is {:?}", interface.annotation)?;
        let traits = match &interface.annotation {
            Some(annotation) => {
                let mut res = vec![];
                if !annotation.has("rust:not-tracked") {
                    res.push("SimpleObjectTracker");
                }
                res
            }
            // No annotation at all, default to tracking.
            None => vec!["SimpleObjectTracker"],
        };
        let other_traits = if traits.is_empty() {
            "".to_owned()
        } else {
            format!(": {}", traits.join("+"))
        };
        writeln!(
            sink,
            "pub trait {}Methods {} {{",
            interface.name, other_traits
        )?;
        // Methods
        for method in interface.methods.values() {
            MethodWriter::declare(&interface.name, &method, sink)?;
            writeln!(sink, ";")?;
        }
        // Members
        for member in &interface.members {
            // member is a (String = name, (Option<Annotation>, ConcreteType, Arity))
            let ctype = member.1;
            let (mtype, _rtype) = rust_type_with_reqresp(&ctype.typ);
            // Getter: get_xxx -> mtype
            // These are infallible.
            writeln!(
                sink,
                "fn get_{}(&mut self, responder: &{}Get{}Responder);",
                member.0,
                interface.name,
                member.0.to_camel_case()
            )?;
            // Setter: set_xxx(mtype)
            // These are infallible.
            writeln!(sink, "fn set_{}(&mut self, value: {});", member.0, mtype)?;
        }
        writeln!(sink, "}}\n")?;
        if !interface.events.is_empty() {
            // Events: we create a struct usable as an event dispatcher.
            writeln!(sink, "#[derive(Clone)]")?;
            writeln!(sink, "pub struct {}EventDispatcher {{", interface.name)?;
            writeln!(sink, "helper: SessionSupport,")?;
            writeln!(sink, "object_id: TrackerId,")?;
            writeln!(sink, "}}\n")?;
            writeln!(sink, "impl {}EventDispatcher {{", interface.name)?;
            writeln!(
                sink,
                "pub fn from(helper: SessionSupport, object_id: TrackerId) -> Self {{"
            )?;
            writeln!(sink, " Self {{ helper, object_id }} }}\n")?;
            for (index, event) in interface.events.values().enumerate() {
                let ctype = &event.returns;
                let (rtype, _itype) = rust_type_with_reqresp(&ctype);
                if rtype != "()" {
                    writeln!(
                        sink,
                        "pub fn dispatch_{}(&self, value: {}) {{",
                        event.name, rtype,
                    )?;
                } else {
                    writeln!(sink, "pub fn dispatch_{}(&self) {{", event.name,)?;
                }
                writeln!(
                    sink,
                    "let service_id = self.helper.session_tracker_id().service();"
                )?;
                writeln!(sink,
                    "if is_event_in_map(&self.helper.event_map(), service_id, self.object_id, {}) {{",
                    index
                )?;
                let event_name = event.name.to_camel_case();
                let enum_value = if ctype.typ != ConcreteType::Void {
                    format!(
                        "{}ToClient::{}{}Event(value)",
                        self.toplevel_name, interface.name, event_name
                    )
                } else {
                    format!(
                        "{}ToClient::{}{}Event",
                        self.toplevel_name, interface.name, event_name
                    )
                };
                writeln!(sink, "let message = BaseMessage {{ service: service_id, object: self.object_id, kind: BaseMessageKind::Event, content: vec![] }};")?;
                writeln!(
                    sink,
                    "self.helper.serialize_message(&message, &{});",
                    enum_value
                )?;
                writeln!(sink, "}}")?;
                writeln!(sink, "}}\n")?;
            }
            writeln!(sink, "}}\n")?;
            // Events: we create a struct usable as an event broadcaster.
            writeln!(sink, "#[derive(Default)]")?;
            writeln!(sink, "pub struct {}EventBroadcaster {{", interface.name)?;
            writeln!(sink, "id: DispatcherId,")?;
            writeln!(
                sink,
                "dispatchers: HashMap<DispatcherId, {}EventDispatcher>,",
                interface.name
            )?;
            writeln!(sink, "}}\n")?;
            writeln!(sink, "impl {}EventBroadcaster {{", interface.name)?;
            writeln!(
                sink,
                r#"pub fn add(&mut self, dispatcher: &{}EventDispatcher) -> DispatcherId {{
                self.id += 1;
                self.dispatchers.insert(self.id, dispatcher.clone());
                self.id
            }}
            pub fn remove(&mut self, dispatcher_id: DispatcherId) {{
                self.dispatchers.remove(&dispatcher_id);
            }}"#,
                interface.name
            )?;
            for event in interface.events.values() {
                let ctype = &event.returns;
                let event_name = &event.name;
                let (rtype, _itype) = rust_type_with_reqresp(&ctype);
                if rtype != "()" {
                    writeln!(
                        sink,
                        "pub fn broadcast_{}(&self, value: {}) {{",
                        event_name, rtype,
                    )?;
                    if needs_clone(&ctype) {
                        writeln!(
                            sink,
                            r#"for dispatcher in &self.dispatchers {{
                        dispatcher.1.dispatch_{}(value.clone());
                    }}"#,
                            event_name
                        )?;
                    } else {
                        writeln!(
                            sink,
                            r#"for dispatcher in &self.dispatchers {{
                        dispatcher.1.dispatch_{}(value);
                    }}"#,
                            event_name
                        )?;
                    }
                } else {
                    writeln!(sink, "pub fn broadcast_{}(&self) {{", event_name)?;
                    writeln!(
                        sink,
                        r#"for dispatcher in &self.dispatchers {{
                        dispatcher.1.dispatch_{}();
                    }}"#,
                        event_name
                    )?;
                }
                writeln!(sink, "}}\n")?;
            }
            writeln!(sink, "}}\n")?;
        }
        Ok(())
    }
pub fn generate_interface < ' a , W : Write > ( & self , interface : & Interface , sink : & ' a mut W , ) -> Result < ( ) > { writeln ! ( sink " " interface annotation ) ? ; let traits = match & interface . annotation { Some ( annotation ) => { let mut res = vec ! [ ] ; if ! annotation . has ( " " ) { res . push ( " " ) ; } res } // No annotation at all, default to tracking. None => vec ! [ " " ] , } ; let other_traits = if traits . is_empty ( ) { " " . to_owned ( ) } else { format ! ( " " traits join ( " " ) ) } ; writeln ! ( sink " " interface name other_traits ) ? ; // Methods for method in interface . methods . values ( ) { MethodWriter :: declare ( & interface . name , & method , sink ) ? ; writeln ! ( sink " " ) ? ; } // Members for member in & interface . members { // member is a (String = name, (Option<Annotation>, ConcreteType, Arity)) let ctype = member . 1 ; let ( mtype , _rtype ) = rust_type_with_reqresp ( & ctype . typ ) ; // Getter: get_xxx -> mtype // These are infallible. writeln ! ( sink " " member 0 interface name member 0 to_camel_case ( ) ) ? ; // Setter: set_xxx(mtype) // These are infallible. writeln ! ( sink " " member 0 mtype ) ? ; } writeln ! ( sink " \n " ) ? ; if ! interface . events . is_empty ( ) { // Events: we create a struct usable as an event dispatcher. writeln ! ( sink " " ) ? ; writeln ! ( sink " " interface name ) ? ; writeln ! ( sink " " ) ? ; writeln ! ( sink " " ) ? ; writeln ! ( sink " \n " ) ? ; writeln ! ( sink " " interface name ) ? ; writeln ! ( sink " " ) ? ; writeln ! ( sink " \n " ) ? ; for ( index , event ) in interface . events . values ( ) . enumerate ( ) { let ctype = & event . returns ; let ( rtype , _itype ) = rust_type_with_reqresp ( & ctype ) ; if rtype != " " { writeln ! ( sink " " event name rtype ) ? ; } else { writeln ! ( sink " " event name ) ? ; } writeln ! ( sink " " ) ? ; writeln ! ( sink " " index ) ? ; let event_name = event . name . to_camel_case ( ) ; let enum_value = if ctype . typ != ConcreteType :: Void { format ! ( " " self toplevel_name interface name event_name ) } else { format ! ( " " self toplevel_name interface name event_name ) } ; writeln ! ( sink " " ) ? ; writeln ! ( sink " " enum_value ) ? ; writeln ! ( sink " " ) ? ; writeln ! ( sink " \n " ) ? ; } writeln ! ( sink " \n " ) ? ; // Events: we create a struct usable as an event broadcaster. writeln ! ( sink " " ) ? ; writeln ! ( sink " " interface name ) ? ; writeln ! ( sink " " ) ? ; writeln ! ( sink " " interface name ) ? ; writeln ! ( sink " \n " ) ? ; writeln ! ( sink " " interface name ) ? ; writeln ! ( sink r#"pub fn add(&mut self, dispatcher: &{}EventDispatcher) -> DispatcherId {{
                self.id += 1;
                self.dispatchers.insert(self.id, dispatcher.clone());
                self.id
            }}
            pub fn remove(&mut self, dispatcher_id: DispatcherId) {{
                self.dispatchers.remove(&dispatcher_id);
            }}"# interface name ) ? ; for event in interface . events . values ( ) { let ctype = & event . returns ; let event_name = & event . name ; let ( rtype , _itype ) = rust_type_with_reqresp ( & ctype ) ; if rtype != " " { writeln ! ( sink " " event_name rtype ) ? ; if needs_clone ( & ctype ) { writeln ! ( sink r#"for dispatcher in &self.dispatchers {{
                        dispatcher.1.dispatch_{}(value.clone());
                    }}"# event_name ) ? ; } else { writeln ! ( sink r#"for dispatcher in &self.dispatchers {{
                        dispatcher.1.dispatch_{}(value);
                    }}"# event_name ) ? ; } } else { writeln ! ( sink " " event_name ) ? ; writeln ! ( sink r#"for dispatcher in &self.dispatchers {{
                        dispatcher.1.dispatch_{}();
                    }}"# event_name ) ? ; } writeln ! ( sink " \n " ) ? ; } writeln ! ( sink " \n " ) ? ; } Ok ( ( ) ) }
Interfaces are mapped to traits.
Interfaces are mapped to traits .
&self
interface
&Interface
sink
&'a mut W