DEV Community

Cover image for Kicking off GSoC: Under the Hood of PR #352 of serialport
Tanmay
Tanmay

Posted on

Kicking off GSoC: Under the Hood of PR #352 of serialport

About Serialport:

The serialport-rs library is a foundational cross-platform crate that enables Rust applications to communicate directly with hardware via serial ports. It serves as a vital bridge in the Rust embedded and robotics communities, allowing developers to reliably interface host machines with microcontrollers, sensors, and autonomous systems. To kick off my Google Summer of Code journey, my PR (#352) overhauls the codebase by stripping out the library's legacy dynamic dispatch architecture in favor of a faster, strictly encapsulated concrete implementation.

The Death of Box<dyn SerialPort>

Maybe the most prominent feature of this version of the library is the elimination of the Box<dyn SerialPort> type. Before, much use was made of trait objects within the framework of dynamic dispatch to deal with various ports. This was an efficient solution, although it came with some overhead in the form of run-time costs and awkward APIs.
Elimination of dynamic dispatch allows us to take full advantage of all that the compiler can do for us from optimizing our code to performing inline substitution where possible. In essence, this results in a more robust library with a nicer API overall.

Unifying the Structs and Hiding the Internals

Platform-specific implementations, such as TTYPort in the case of POSIX systems and COMPort in Windows, were directly exposed to the outside world. The result of this approach was that OS-specific implementation details were getting leaked into user space, thus breaking a fragile contract between the library and its users
PR #352 fixes this by unifying the platform-specific implementations into a single, clean public interface:

pub struct SerialPort(pub(crate) sys::SerialPort);

Both TTYPort and COMPort have been removed completely from the public API. As a result, we have provided the maximum amount of freedom for future refactoring to the people who will be maintaining the library in the future by ensuring that we can now change how things work internally without worrying about breaking downstream code that relied on those specific struct names.

The POSIX Extension Trait

However, once again there appeared a new problem. How can we make platform specific implementations available when all is encapsulated in our new SerialPort struct?
And the very nice way to deal with this situation was the introduction of extension traits. The platform specific methods such as .pair() and .exclusive() have been moved into the new trait SerialPortExt. Thus, the SerialPort itself remains cross-platform but you can add POSIX abilities if necessary.

Re-exporting the Extension Trait

At first, I had implemented the extension feature by putting it in the mod.rs file. But my mentor Sirchel suggested an alternate method where I would implement the code in a separate file and re-export it at the root.

The Road Ahead

PR #352 was certainly something which was most needed and was successfully implemented right at the start of the project. With a switch towards concrete types, tight encapsulation, and use of extension traits, there’s been a huge improvement in architecture that we’re dealing with here. Not only is the next generation of serialport-rs way better in performance and security, but it's much more maintainable as well!

This gives an excellent starting point for the upcoming weeks, and I couldn’t be happier about how things are shaping up thus far!

Top comments (0)