Alors voila, je veux écrire une fonction qui appelle une commande shell et retourne la chaîne de caractères.
Avec la cagette standard std::process::Command c’est plutôt simple il suffit de faire ça :
use std::process::Command;
//..
let _cmdret = Command::new("cd-discid")
.output()
.expect("La commande cd-discid a échouée");
//..
Langage du code : PHP (php)
L’affichage de _cmdret avec un println! qui va bien me donne la forme de la structure retournée :
println!("{:?}", &_cmdret);
//:Sortie ->
Output { status: ExitStatus(unix_wait_status(0)), stdout: "30027f05 5 150 2422 15072 29219 44022 641\n", stderr: "" }
Langage du code : JavaScript (javascript)
Pour le moment c’est assez simple, si je veux récupérer la chaîne de caractères, il me suffit de prendre le champs stdout
:
println!("{:?}", &_cmdret.stdout);
//...
[51, 48, 48, 50, 55, 102, 48, 53, 32, 53, 32, 49, 53, 48, 32, 50, 52, 50, 50, 32, 49, 53, 48, 55, 50, 32, 50, 57, 50, 49, 57, 32, 52, 52, 48, 50, 50, 32, 54, 52, 49, 10]
Langage du code : JavaScript (javascript)
Rhaa, mais pourquoi ça s’est transformé en vecteur de u8 ?!
Allons bon, convertissons avec std::str :
use std::str
///
println!("{:?}", str::from_utf8(&_cmdret.stdout));
///sortie ->
Ok("30027f05 5 150 2422 15072 29219 44022 641\n")
Langage du code : JavaScript (javascript)
On obtient donc une sortie de type Result non ? Notre fonction doit pouvoir s’écrire comme ça alors :
/// Lit le numéro unique du CD se trouvant dans le lecteur
pub fn get_discid() -> Result<String, Box<dyn Error>> {
let _cmdret = Command::new("cd-discid")
.output()
.expect("La commande cd-discid a échouée");
str::from_utf8(&_cmdret.stdout)
}
Langage du code : JavaScript (javascript)
Sauf que non, ce que je croyais être un enum «Result» c’est transformé en une chaîne de caractères &str :
22 | str::from_utf8(&_cmdret.stdout)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::string::String`, found `&str`
Langage du code : PHP (php)
Rajoutons un Ok() pour lui faire plaisir alors :
22 | Ok(str::from_utf8(&_cmdret.stdout))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::string::String`, found enum `Result`
Langage du code : PHP (php)
Et c’est là que je commence à perdre pied, bin oui t’as trouvé un enum Result, puisque c’est ça que j’attends en retour patate !
En browsant désespérément le web j’ai cru trouver qu’il fallait faire un match sur l’enum pour retourner un nouvel enum (mais j’ai pas compris pourquoi le premier ne convenait pas):
/// Lit le numéro unique du CD se trouvant dans le lecteur
pub fn get_discid() -> Result<String, Box<dyn Error>> {
let _cmdret = Command::new("cd-discid")
.output()
.expect("La commande cd-discid a échouée");
match str::from_utf8(&_cmdret.stdout) {
Ok(v) => Ok(v.to_string()),
Err(e) => Err(e.into())
}
}
Langage du code : JavaScript (javascript)
À noter qu’il est possible de remplacer le to_string() en into() dans le Ok()
mais pas pour le Err()
.
Bon maintenant ça marche. Mais il me reste un goût amer de celui qui n’a pas compris ce qu’il a écrit. Et j’ai la désagréable impression d’avoir tartiné du code pour pas grand chose !
On doit pouvoir faire plus simple non ?
Bref, la route est encore longue, et c’est pas ce soir que je verrais mes recettes d’histoires terminées 😉
On peut faire
Ok(std::str::from_utf8(&cmdret.stdout)?.to_string())
.De mémoire le
?
va automatiquement chercher à convertir l’erreur dans le type attendu en retour, ce qui évite uninto()
explicite.Autre avantage, si jamais on veut faire un traitement derrière sur la chaîne retournée, c’est plus facile. Par exemple :
Quand tu dis « bin oui t’as trouvé un enum Result, puisque c’est ça que j’attends », tu ne fais pas attention à la partie « soulignée » de l’erreur, qui n’inclue pas le
Ok
.Merci ~ryder 🙂
Le
?
simplifie en effet le code et fonctionne bien.J’avoue avoir fait un raccourci foireux. Mon problème est que si je supprime le
Ok()
, en toute logique, je suis sensé me retrouver avec unenum
de typeResult
non ?Or ça n’est pas le cas, si je fait ça le compilateur voit un
&str
! Il faudrait savoir.