I'm defining a crate API in Rust stable (as of now, version 1.2) and am perplexed about best practices for defining my own string-like types.
For example, I have a Foo
type that wraps a string.
pub struct Foo(String);
My API hides construction of Foo
instances, and, furthermore, because the tuple field is private, the application cannot mistakenly construct an invalid Foo
value for itself. This means my API restricts the application to work only with valid Foo
values. So far so good.
However, I want the application to be able to use a Foo
instance as though it's a string—say, printing it, logging it, writing it to a file, passing it to a third-party crate that accepts &str
, constructing a copy via to_string()
and mutating the copy, etc. In short, I want the application to be able to “cast away” Foo
-ness and work with a reference to the underlying string. Because the application cannot convert the raw string back into a Foo
instance, type-safety is preserved.
My question is: What conversion traits, if any, should my crate implement for Foo
to allow the application to “cast away” Foo
-ness and work with the underlying string as a raw string? It's important that Foo
convert to &str
so as to obviate any unnecessary copying of the underlying string.
For example, how about?
impl AsRef<str> for Foo
Is that the right thing to do? Is it enough to be idiomatic? Are there any other conversion traits I should consider implementing for Foo
?
If a Foo
is semantically a string, then implementing Deref<Target = str>
(or possibly Deref<Target = String>
and DerefMut
) is the main thing to do. That will allow &Foo
to coerce to &str
, so you can write things like &*foo
to get a &str
out of a Foo
, and foo.starts_with("bar")
and such, calling methods that are defined on str
.
Implementing AsRef
is also going to be beneficial for some things. Borrow
is another thing you may want to have, though there are things to consider before doing so.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With