pub struct ReaperStringArg<'a>(_);
Expand description

A string parameter.

Medium-level API functions with string parameters accept all kinds of strings which can be converted into this type, most notably &CStr and &str.

Design

This is a wrapper around a Cow<ReaperStr>, where ReaperStr is essentially a CStr with UTF-8 guarantee.

Why C strings and not regular Rust strings?

We use a sort of C string because that perfectly accounts for the medium-level API’s design goal to be still as close to the original REAPER API as possible (while at the same time introducing Rust’s type safety). The C++ REAPER API generally expects C strings (*const c_char). Fortunately UTF-8 encoded ones - which makes a character set conversion unnecessary.

Why &CStr and not *const c_char?

We don’t use *const c_char directly because we want more type safety. We use &CStr instead because in Rust that’s the closest thing to a *const c_char (infact it’s the same + some additional guarantees). It’s a reference instead of a pointer so we can assume it’s neither stale nor null. Also, the &CStr type gives us important guarantees, for example that there are no intermediate zero bytes - which would make the string end abruptly in C world.

Why Cow and ReaperStringArg?

We don’t use just a plain &CStr as parameter type because &CStr is not the regular string type in Rust. It’s much harder to create and use than &str. We want the API to be a pleasure to use! That’s the reason for adding ReaperStringArg and Cow to the mix. Cowis necessary because we might need to own a possible conversion result (e.g. from &str). ReaperStringArg is necessary to offer implicit conversions from regular Rust string types. Because medium-level API functions take string parameters as impl Into<ReaperStringArg>, they just work with regular Rust strings.

Performance considerations

A conversion from a regular Rust string is not entirely without cost because we need to check for intermediate zero bytes and append a zero byte (which demands a copy if a borrowed string is passed)! Therefore, if you want to be sure to not waste any performance and you can get cheap access to a C string, just pass that one directly. Then there’s no extra cost involved. In many scenarios this is probably over optimization, but the point is, you can go the zero-cost way, if you want.

In the reaper-rs code base you will find many examples that pass c_str!("...") to string parameters. This macro from the c_str_macro crate creates static (UTF-8 encoded) &CStr literals, just as "..." creates static &str literals. Because those literals are embedded in the binary itself, no heap-space allocation or conversion is necessary at all. If you want, you can do the same with your literals.

Implementations

Consumes this value and spits out the contained cow.

If you decide to use my_param: impl Into<ReaperStringArg<'a>> somewhere in your own REAPER plug-in or library code in order to benefit from the same safe conversions that reaper-rs offers, this method is for you. Once you have the ReaperStringArg by calling my_param.into(), there’s no getting around calling this method first to obtain the inner cow, which you can then use to convert it to any string type that you desire. There are no convenience methods because ReaperStringArg is really just something very intermediate, solely intended for automatic conversion.

Trait Implementations

Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more
Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait. Read more
Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait. Read more
Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s. Read more
Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s. Read more
Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.