2015-09-14 8 views
11

Sto definendo un'API di crate in Rust stable (come ora, versione 1.2) e sono perplesso sulle best practice per definire i miei tipi di stringhe.Quando utilizzare AsRef o altri tratti di conversione per tipo stringa

Ad esempio, ho un tipo Foo che avvolge una stringa.

pub struct Foo(String); 

mio API nasconde costruzione di Foo casi, e, inoltre, perché il campo tupla è privato, l'applicazione non può costruire erroneamente un valore non valido Foo per se stessa. Ciò significa che la mia API limita l'applicazione a funzionare solo con valori validi . Fin qui tutto bene.

Tuttavia, voglio l'applicazione per essere in grado di utilizzare un'istanza Foo come se fosse una stringa-dire, stamparlo, la registrazione, scrivendo in un file, passandolo a una cassa di terze parti che accetta &str, costruendo una copia tramite to_string() e cambiando la copia, ecc. In breve, voglio che l'applicazione sia in grado di "scartare" Foo -ness e lavorare con un riferimento alla stringa sottostante. Poiché l'applicazione non è in grado di convertire nuovamente la stringa non elaborata in un'istanza Foo, la sicurezza del tipo viene mantenuta.

La mia domanda è: Che cosa tratti di conversione, se del caso, dovrebbero mia cassa implementare per Foo per consentire l'applicazione a “gettato via” Foo -ness e lavorare con la stringa sottostante come una stringa crudo? È importante convertirein &str in modo da evitare qualsiasi copia non necessaria della stringa sottostante.

Ad esempio, che ne dici?

impl AsRef<str> for Foo 

È la cosa giusta da fare? È sufficiente essere idiomatici? Ci sono altri tratti di conversione che dovrei considerare di implementare per Foo?

risposta

8

Se un Fooè semanticamente una stringa, quindi attuazione Deref<Target = str> (o, eventualmente, Deref<Target = String> e DerefMut) è la cosa principale da fare. Ciò consentirà di &Foo di coercitare a &str, quindi è possibile scrivere cose come &*foo per ottenere un &str su un Foo e foo.starts_with("bar") e tali metodi di chiamata sono definiti su str.

L'implementazione di AsRef sarà utile per alcune cose. Borrow è un'altra cosa che può desidera avere, though there are things to consider before doing so.

+1

L'esempio 'starts_with' cancella molto. Comunque, ho letto la sezione del libro su 'AsRef' e' Borrow' - non ancora chiaro. 'AsRef' consente la coercizione in un' & str' ma senza tenere conto dell'esempio 'starts_with'? Quali sono alcuni casi in cui dovrei implementare 'AsRef invece di' Deref'? Dovrei mai implementare entrambi? –

+2

'Deref' è magico e può essere fatto per un tipo. 'AsRef' è completamente non magico e può essere fatto per più tipi. L'implementazione di entrambi è comune. –

Problemi correlati