fn write_encoder_for_item<'a, W: Write>(
        &self,
        path: &str,
        item: &'a TypeItem,
        sink: &'a mut W,
    ) -> Result<()> {
        // The full name of the JS property.
        let mut full_path = match &item.name {
            Some(val) => format!("{}.{}", path, val),
            None => path.into(),
        };

        let postfix = match item.typ.arity {
            Arity::Unary => "",
            Arity::Optional => {
                // For optional arity, we enclose in |if (!!full_path) { ... }|
                writeln!(sink, "result = result.bool({} !== undefined);", full_path)?;
                writeln!(sink, "if ({} !== undefined) {{", full_path)?;

                "}\n"
            }
            Arity::ZeroOrMore => {
                // TODO: Check that the full_path is an array.
                writeln!(
                    sink,
                    "result = result.bool({} !== undefined && {}.length > 0);",
                    full_path, full_path
                )?;
                writeln!(
                    sink,
                    "if ({} !== undefined && {}.length > 0) {{",
                    full_path, full_path
                )?;
                writeln!(sink, "result = result.u64({}.length);", full_path)?;
                writeln!(sink, "{}.forEach(item => {{", full_path)?;

                full_path = "item".into();

                "});\n }\n"
            }
            Arity::OneOrMore => {
                // Multiple occurences are turned into arrays that are iterated over.
                // First write the array length.
                // TODO: Check that the full_path is an array.
                writeln!(sink, "result = result.u64({}.length);", full_path)?;
                writeln!(sink, "{}.forEach(item => {{", full_path)?;

                full_path = "item".into();

                "});\n"
            }
        };

        match item.typ.typ {
            ConcreteType::Dictionary(ref utype) => {
                // For dictionaries, we serialize each field in sequence.
                let dict = self.ast.dictionaries.get(utype).unwrap();
                // If the full path is just "item" that means we are in an array
                // loop already, so no need to create another dictionary holder.
                if full_path != "item" {
                    writeln!(sink, "let dict = {};", full_path)?;
                    full_path = "dict".into();
                }

                // Create a new item type for each property.
                for member in &dict.members {
                    self.write_encoder_for_item(
                        &full_path,
                        &TypeItem::from(Some(member.name.clone()), &member.typ),
                        sink,
                    )?;
                }
            }
            ConcreteType::Enumeration(_) => {
                // Enumerations are just variant tag values.
                writeln!(sink, "result = result.enum_tag({});", full_path)?;
            }
            ConcreteType::Callback(_) | ConcreteType::Interface(_) => {
                // For interfaces, we output the object id.
                writeln!(sink, "result = result.u32({}.id);", full_path)?;
            }
            _ => {
                writeln!(
                    sink,
                    "result = result.{}({});",
                    js_type(&item.typ.typ),
                    full_path
                )?;
            }
        }

        sink.write_all(postfix.as_bytes())?;

        Ok(())
    }
// path is the current "root" seeding the JS property.
path is the current "root" seeding the JS property.
path is the current " root " seeding the JS property .
fn write_encoder_for_item<'a, W: Write>(
        &self,
        path: &str,
        item: &'a TypeItem,
        sink: &'a mut W,
    ) -> Result<()> {
        // The full name of the JS property.
        let mut full_path = match &item.name {
            Some(val) => format!("{}.{}", path, val),
            None => path.into(),
        };
        let postfix = match item.typ.arity {
            Arity::Unary => "",
            Arity::Optional => {
                // For optional arity, we enclose in |if (!!full_path) { ... }|
                writeln!(sink, "result = result.bool({} !== undefined);", full_path)?;
                writeln!(sink, "if ({} !== undefined) {{", full_path)?;
                "}\n"
            }
            Arity::ZeroOrMore => {
                // TODO: Check that the full_path is an array.
                writeln!(
                    sink,
                    "result = result.bool({} !== undefined && {}.length > 0);",
                    full_path, full_path
                )?;
                writeln!(
                    sink,
                    "if ({} !== undefined && {}.length > 0) {{",
                    full_path, full_path
                )?;
                writeln!(sink, "result = result.u64({}.length);", full_path)?;
                writeln!(sink, "{}.forEach(item => {{", full_path)?;
                full_path = "item".into();
                "});\n }\n"
            }
            Arity::OneOrMore => {
                // Multiple occurences are turned into arrays that are iterated over.
                // First write the array length.
                // TODO: Check that the full_path is an array.
                writeln!(sink, "result = result.u64({}.length);", full_path)?;
                writeln!(sink, "{}.forEach(item => {{", full_path)?;
                full_path = "item".into();
                "});\n"
            }
        };
        match item.typ.typ {
            ConcreteType::Dictionary(ref utype) => {
                // For dictionaries, we serialize each field in sequence.
                let dict = self.ast.dictionaries.get(utype).unwrap();
                // If the full path is just "item" that means we are in an array
                // loop already, so no need to create another dictionary holder.
                if full_path != "item" {
                    writeln!(sink, "let dict = {};", full_path)?;
                    full_path = "dict".into();
                }
                // Create a new item type for each property.
                for member in &dict.members {
                    self.write_encoder_for_item(
                        &full_path,
                        &TypeItem::from(Some(member.name.clone()), &member.typ),
                        sink,
                    )?;
                }
            }
            ConcreteType::Enumeration(_) => {
                // Enumerations are just variant tag values.
                writeln!(sink, "result = result.enum_tag({});", full_path)?;
            }
            ConcreteType::Callback(_) | ConcreteType::Interface(_) => {
                // For interfaces, we output the object id.
                writeln!(sink, "result = result.u32({}.id);", full_path)?;
            }
            _ => {
                writeln!(
                    sink,
                    "result = result.{}({});",
                    js_type(&item.typ.typ),
                    full_path
                )?;
            }
        }
        sink.write_all(postfix.as_bytes())?;
        Ok(())
    }
fn write_encoder_for_item < ' a , W : Write > ( & self , path : & str , item : & ' a TypeItem , sink : & ' a mut W , ) -> Result < ( ) > { // The full name of the JS property. let mut full_path = match & item . name { Some ( val ) => format ! ( " " path val ) , None => path . into ( ) , } ; let postfix = match item . typ . arity { Arity :: Unary => " " , Arity :: Optional => { // For optional arity, we enclose in |if (!!full_path) { ... }| writeln ! ( sink " " full_path ) ? ; writeln ! ( sink " " full_path ) ? ; " \n " } Arity :: ZeroOrMore => { // TODO: Check that the full_path is an array. writeln ! ( sink " " full_path full_path ) ? ; writeln ! ( sink " " full_path full_path ) ? ; writeln ! ( sink " " full_path ) ? ; writeln ! ( sink " " full_path ) ? ; full_path = " " . into ( ) ; " \n \n " } Arity :: OneOrMore => { // Multiple occurences are turned into arrays that are iterated over. // First write the array length. // TODO: Check that the full_path is an array. writeln ! ( sink " " full_path ) ? ; writeln ! ( sink " " full_path ) ? ; full_path = " " . into ( ) ; " \n " } } ; match item . typ . typ { ConcreteType :: Dictionary ( ref utype ) => { // For dictionaries, we serialize each field in sequence. let dict = self . ast . dictionaries . get ( utype ) . unwrap ( ) ; // If the full path is just "item" that means we are in an array // loop already, so no need to create another dictionary holder. if full_path != " " { writeln ! ( sink " " full_path ) ? ; full_path = " " . into ( ) ; } // Create a new item type for each property. for member in & dict . members { self . write_encoder_for_item ( & full_path , & TypeItem :: from ( Some ( member . name . clone ( ) ) , & member . typ ) , sink , ) ? ; } } ConcreteType :: Enumeration ( _ ) => { // Enumerations are just variant tag values. writeln ! ( sink " " full_path ) ? ; } ConcreteType :: Callback ( _ ) | ConcreteType :: Interface ( _ ) => { // For interfaces, we output the object id. writeln ! ( sink " " full_path ) ? ; } _ => { writeln ! ( sink " " js_type ( item typ typ ) full_path ) ? ; } } sink . write_all ( postfix . as_bytes ( ) ) ? ; Ok ( ( ) ) }
path is the current "root" seeding the JS property.
path is the current " root " seeding the JS property .
&self
path
&str
item
&'a TypeItem
sink
&'a mut W
&self
path
&str
item
&'a TypeItem
sink
&'a mut W