«Недостаточно общая» ошибка десериализации YAML

#rust #serde

#Ржавчина #serde

Вопрос:

Я новичок в Rust, поэтому я уверен, что мне не удается найти здесь что-то элементарное, но…

У меня есть файл конфигурации yaml, который я хочу десериализовать в простую структуру. В более ранней версии я мог нормально выполнять это из строкового литерала, но теперь, когда я переработал его для чтения из файла, я получаю сообщение об ошибке implementation of '_::_serde::Deserialize' is not general enough . Моя функция выглядит так:

 fn read_config(file: amp;str) -> Result<Config, amp;'static str> {
    match std::fs::read_to_string(file) {
        Ok(yaml) => match serde_yaml::from_str(amp;yaml) {
            Ok(c) => c,
            Err(_) => Err("Failed to parse yaml config."),
        },
        Err(_) => Err("Could not open supplied config file"),
    }
}
  

read_to_string возвращает a Result<String> , но подпись для serde_yaml::from_str требует amp;str , то есть заимствования. Когда я даю ему заимствование, как указано выше, я получаю ошибку «недостаточно общая». Когда я гуглю эту ошибку, я вижу много дискуссий о том, что десериализатор не может использовать заимствованные данные; сначала я должен владеть ими. Разве это не то, что в оригинале String ? Если from_str нельзя использовать заимствование, почему оно принимает amp;str в качестве аргумента? Чего мне здесь не хватает?

Ответ №1:

Проблема не в переданном вами строковом параметре.

Согласно документации, from_str возвращает Result<T> . В этом случае вам нужно будет вызвать функцию с ожидаемым типом для T . Здесь это было бы serde_yaml::from_str::<Config>(amp;yaml) .

Вам также необходимо исправить свой оператор возврата для c . Это было бы Ok(c) , не только c .

Комментарии:

1. Да, я понял это так же, как вы опубликовали. ::<Config> Является избыточным, если возврат исправлен, но это все. Спасибо!

2. Я опубликовал свой ответ всего на секунду позже, кажется, вы уже нашли решение. Вы правы, вывод типа не произошел из-за оператора return, он действительно избыточен.

Ответ №2:

Конечно же, я упустил что-то фундаментальное. Проблема не имела ничего общего с заимствованиями или владением. Я пропустил перенос конечного результата в Ok() , что испортило вывод типа для моего вызова from_str . Исправленная функция:

 fn read_config(file: amp;str) -> Result<Config, amp;'static str> {    
    match std::fs::read_to_string(file) {        
        Ok(yaml) => match serde_yaml::from_str(amp;yaml) {
            Ok(c) => Ok(c),
            Err(_) => Err("Failed to parse yaml config."),
        },
        Err(_) => Err("Could not open supplied config file"),
    }
}