Получить перечисление как строку

У меня есть перечисление со многими значениями

enum Foo {
  Bar = 0x00,
  Baz = 0x01,
  Qux = 0x02,
  ...
  Quux = 0xFF
}

и иногда я хотел бы записать имя одного из его значений в поток. Я могу получить Debug и сделать

writer.write(format!("I am {:?}", Foo::Quux).as_bytes())

который будет выводиться, например. I am Quux. Это прекрасно, за исключением того, что

  • Я хочу сделать это для вывода, ориентированного на пользователя, поэтому отладка не подходит
  • Было бы очень полезно получить перечисление в виде строки (а не напрямую писать в поток), потому что тогда я могу включить ее длину в некоторые неуловимые вычисления форматирования, которые я хочу сделать.

Какой лучший способ достичь этого?

Ответ 1

Вероятно, самым простым способом было бы реализовать Display путем вызова в Debug:

impl fmt::Display for Foo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self)
        // or, alternatively:
        // fmt::Debug::fmt(self, f)
    }
}

Затем вы можете использовать to_string(), чтобы получить представление String:

let s: String = Foo::Quux.to_string();

Если у вас много переписей, которые вы хотите распечатать, вы можете написать тривиальный макрос, чтобы создать вышеприведенную реализацию Display для каждого из них.

К сожалению, в Rust рефлексивное программирование несколько сложно. Нет стандартного способа, например, получить список всех вариантов C-подобного перечисления. Почти всегда вам приходится абстрагироваться от шаблона с помощью написанных пользователем макросов (или найти что-то на crates.io). Возможно, это изменится в будущем, если кто-то напишет RFC, и он будет принят.