Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use AsRef or other conversion traits for string-like type

Tags:

rust

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?

like image 903
Craig M. Brandenburg Avatar asked Sep 14 '15 03:09

Craig M. Brandenburg


1 Answers

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.

like image 131
Chris Morgan Avatar answered Oct 12 '22 09:10

Chris Morgan