Conf42 Rustlang 2023 - Online

Rust Code Prototyping using XML

Video size:

Abstract

Inspired by Google Protocol Buffers, I created an experimental project that generates Rust code from XML prototype or modeling. I will discuss about the project, the concepts and usages. This includes how the XML is formatted. I will also present the demo code with test assertions.

Summary

  • RustxmL Proto's main objective is to create a tool or library that can auto generate rust code from struct traits,enum, and other object definitions by modeling them through XML. XmL proto is inspired by Google protocol buffers. I made this tool to generate rustcode easily from XML data.
  • Next, let's discuss the attributes of prototype element. This will be also used to name the module itself. For members and functions you have the child elements. Visibility describes the visibility of our object. All objects in the imported module can be used independently.
  • For macros we have first derive, so it defines new inputs for the derived attribute serdi. If you have created customized macros or other macros other than derive and serde, you can define them under custom XML element. In procedural macros you can also indicate a set of traits.

Transcript

This transcript was autogenerated. To make changes, submit a PR.
So let us start rust code prototyping using XML or what I shortly name as rust. XmL proto is inspired by Google protocol buffers. I made this tool to generate rust code easily from XML data. I started this project few months after I learned about Rust, and this I've done to explore more about the language itself. So first of all, what is a protocol buffer? So a protocol buffer is an open source, cross platform project that is used to serialize structured data that can be transmitted or stored in files. Protobuffs, however, are much faster than XML and Json. You can see from the left image an example of how protobuff is defined. So in this definition we have person as our object with members name having string data type id with int 32 data type, and email with string data type. On the right side we can see how it can be used in the code, so it builds the person name John Doe with values 1234 for id, jando for name email is jdo@xml.com and then for protocol it used the function build to generate the structure for this object John and then afterwards it writes the object into a file output stream. In our project, XML structure or format is used for the prototype instead. Now RustxmL Proto's main objective is to create a tool or library that can auto generate rust code from struct traits, enum, and other object definitions by modeling them through XML. There are other auto generating tools for code that I've encountered, starting from my previous company that I joined until the current company, but I haven't seen anyone yet that usages rust language for it and for the purpose of generating rust code. So here's a preview or example of how the XML format is defined for a ROS object. In my project I will describe the XmL elements tag names, attribute names, and attribute values in the later slides. And here is how to use the Raz XML proto object in a module. You only have to use import proto macro function with the object name as a parameter. So we have import underscore proto with value fubar as our object name. Now I am going to describe the main or major XML elements for our object definitions. We have the root element that needs to be defined as the prototype. This is ultimately required so as to set the object name of our structure. Without this element, the XML data is invalid itself. Next we have prox prox. I shortly name it after the procedural macros. It is literally used to define the procedural macros and custom macros. Next we have members tag name members. Like any other object or structured data, we need member variables. So this we also have to define through members element. Next we have includes includes. With this element we can use or import libraries from external or within the module. And lastly we have functions apart from setters, getters and constructors which are already automatically generated after we run the rust XML tool. We can also declare other functions that we intend to use. If you want to add another function name, integrate with Fubar or whatever you want. Next, let's discuss the attributes of prototype element. So in our prototype element we have the attributes name, which is the object name of our prototype. This will be also used to name the module itself. So if you have Fubar, then our module will name as module rs rs, our extension file. Next attribute is class. It defines the type of our object. So in class we can define that our object can be struct enum or trait visibility. Visibility describes the visibility of our object. So we can have mod, which means that our object will be only allowed to use within the module or created if you want to use only the object inside our crate, external if you want it to be used externally and global, globally and private, the same as mod within the module itself. Next we'll discuss the child elements of includes. So we have includes. We have these child elements as the following within will define that the import module imported modules comes from within our crate. Extern describes that the module we imported is from an external created. So here is an example. We have includes tag element, include and then within that includes you can have a lot of multiple instances of within or external. So within FUBAR, within the module is full bar within and then for external we have the module fuBAR external. Now we have to discuss the attributes of the child elements. So within or extern we can define the scope if defined as all. So all objects in the imported module can be used independently. However, if you want to specify which objects you want to use from the module, you can use objects with a set of values like object one and object two. Now let's go to members and functions. So for members and functions you have the child elements. The tag name of the child element within the member can be any string that referred to a data type. For this example you have string data type for object name item. Then you have u 32 as our data type for object name pride. So another attribute or attribute associated with members and functions is we have visibility like other visibility values, we have mod within the mod created if you want only to use this one inside the created external if you want to access it externally, global, globally and private. The same as mod within the module itself. In functions there is a sub code that can be defined for parameters. So we all know that functions or methods have the parameters or arguments that will be passed from another instance. So here we are parameters. The child element of a parameter is any string that refers to data type. So here like functions or like members, we can define the parameters with string data type u 32 for this example and any string that refers to data type. Also we have child attribute name. This only refers to the name of our argument or members or parameters actually. Next slide we have xml elements for our macros. There are currently three use xml elements. For macros we have first derive, so it defines new inputs for the derived attribute serdi. If you are familiar with serialize and deserialize, you can use Serda to generate implementations of these traits and then custom. If you have created customized macros or other macros other than derive and serde, you can define them under custom XML element. In procedural macros you can also indicate a set of traits. So if you want to use a lot of values inside, for example derive, you have to define it by using the attribute set. Now for our demo code, here's an example for the XML prototype I created for the demo code. We name it as test Proto XML. Since our object name is named as test proto. So here we have prototype as our root element. Without this you cannot generate the rust code. Then we have the name attribute test proto class. So our object type is Chuck and then the visibility. This object can only be accessed inside the crate. After that prototype tag element we can see the includes. So this imports any module you want, any module that we want to use inside our project. So for example we have here external external name using serde. So we are using Serde as our module. Then with object specified as deserialize and serialize. Okay, next after includes we can also define prox I define here prox procedural macros using derive as our XmL element and then inside derive we can define a lot of traits. For example debug, serialize, deserialize. Okay lastly we have members, so we have to set our members for object struct. So in our example or in our project we have string data type for object member name with visibility external so this can be accessed externally. String name string data type for object current for member current address with visibility crate so this member can only be accessed inside the crate. And lastly I 32 data type for member id. So if you don't define the visibility of the member or any object for example here, it's not necessarily to have a visibility attribute. So if it's not defined then it's automatically within the module only. So to use our prototype test proto so it is as presented. So in main rs created the main module as main rs we have first the use proto macro import proto. You will use this so that we can import our proto object. After that we use the macro function import protocol and then our object name test proto. Then inside our function name we have print we print first that we run the demo for test proto and then we use the constructor of test proto. So here it is. Now we can use the generated code object proto with test proto double columns new and then you have our string number Joe Biden this is for a string name Joe Biden and then current address for our object is white house. Also string data type and then id member id is 123-45-6789 so after that, yes, here's an example of how we test assert the values inside our object so we can use assert equal and then get the name of our object compared it to a string Joe Biden. So if it returns true then it passes, right? And then if it passes it will print our string test case prototype Joe Biden passed. So if it fails, then it will stop here and skip the remaining lines. Next we also assert equal. We compare our current address current address with vestring white House. So if it passes then it will print that test case two passes with protocol address as white House. If it fails, then it will stop here and skip the remaining lines. Then next we also compare the id of our object with a value 123-45-6789 if it passes, then it will print the test case three pass with proto id 123-45-6789 and if it fails then it will just stop here. Next, so we have the constructor, we use the constructor of the generated code. Next we will use the setters itself. We can use the setters and getters. I think we already use the getters setters. Let's say we change the name from Joe Biden to Donald Trump so we can use protocol set underscore name with string Donald Trump. After that we compare if the name is already changed with the string Donald Trump. If it passes, then it will print our test case for passed with name Donald Trump. If it fails, then it will stop here. Yeah, and next we change the current address of our object with the string Washington DC. So next, after that we compare again the current address of our object with a string Washington Dc if it passes, then it will print the test case value is passed. Next we try to change try to change the name. We try to change the current address. So lastly, we have to test if our setter for id also working fine. So we use the set underscore id to change the value from 1234-5678-9298-7654-321 and after that we compare. We test if our id changes from 123-45-6789 to 987-65-4321 so if it passes, then it will print that test case six passed with proto id the new value. And if it fails, then it will just print fail for test assertion. I think that's it for my presentation. If you have any questions you can raise. Thank you.
...

John Rexes Murro

Software Engineer @ Amdocs

John Rexes Murro's LinkedIn account



Awesome tech events for

Priority access to all content

Video hallway track

Community chat

Exclusive promotions and giveaways