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.