Struct reaper_medium::ReaperStringArg
source · [−]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. Cow
is 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
sourceimpl<'a> ReaperStringArg<'a>
impl<'a> ReaperStringArg<'a>
sourcepub fn into_inner(self) -> Cow<'a, ReaperStr>
pub fn into_inner(self) -> Cow<'a, ReaperStr>
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
sourceimpl<'a> From<&'a ReaperStr> for ReaperStringArg<'a>
impl<'a> From<&'a ReaperStr> for ReaperStringArg<'a>
sourceimpl<'a> From<&'a str> for ReaperStringArg<'a>
impl<'a> From<&'a str> for ReaperStringArg<'a>
sourceimpl From<ReaperString> for ReaperStringArg<'static>
impl From<ReaperString> for ReaperStringArg<'static>
sourcefn from(s: ReaperString) -> Self
fn from(s: ReaperString) -> Self
Auto Trait Implementations
impl<'a> RefUnwindSafe for ReaperStringArg<'a>
impl<'a> Send for ReaperStringArg<'a>
impl<'a> Sync for ReaperStringArg<'a>
impl<'a> Unpin for ReaperStringArg<'a>
impl<'a> UnwindSafe for ReaperStringArg<'a>
Blanket Implementations
sourceimpl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
const: unstable · sourcefn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
sourceimpl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
sourcefn into_any(self: Box<T, Global>) -> Box<dyn Any + 'static, Global>
fn into_any(self: Box<T, Global>) -> Box<dyn Any + 'static, Global>
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 moresourcefn into_any_rc(self: Rc<T>) -> Rc<dyn Any + 'static>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any + 'static>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
. Read moresourcefn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s. Read moresourcefn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s. Read more