Руководство по средству чтения RSS (использование Rust для Windows с VS Code)

В предыдущем разделе вы узнали о Rust для Windows и крейте windows.

Теперь давайте попробуем Rust для Windows, написав простое консольное приложение, которое скачивает заголовки записей блога из веб-канала действительно простой синдикации (RSS).

  1. Запустите командную строку (cmd.exe) и cd перейдите в папку, в которой хотите хранить свои проекты Rust.

  2. С помощью Cargo создайте проект Rust с именем rss_reader и cd в только что созданную папку:

    > cargo new rss_reader
    >     Created binary (application) `rss_reader` package
    > cd rss_reader
    
  3. Теперь откройте проект rss_reader в VS Code.

    code .
    
  4. Давайте реализуем основной проект rss_reader . Сначала откройте Cargo.toml файл в корне проекта. Файл Cargo.toml — это текстовый файл, описывающий проект Rust, включая все его зависимости.

    Добавьте зависимость от ящика окон , как показано в описании ниже. Ящик окон большой. Чтобы обеспечить быстрое время сборки, мы будем выбирать только Foundation_Collections те функции, Web_Syndication которые нам нужны для этого кода.

    # Cargo.toml
    ...
    
    [dependencies.windows] 
    version = "0.43.0"
    features = [
        "Foundation_Collections",
        "Web_Syndication",
    ]
    
  5. Затем откройте файл исходного src/main.rs кода проекта rss_reader. Там вы найдете код по умолчанию Cargo "Hello, world!". Добавьте следующую инструкцию use в начало main.rs:

    // src\main.rs
    use windows::{
        core::*,
        Foundation::Uri,
        Web::Syndication::SyndicationClient
    };
    
    fn main() {
        println!("Hello, world!");
    }
    

    Объявление использования сокращает путь к типам, которые мы будем использовать. Также указан тип Uri, упомянутый ранее.

  6. Чтобы создать новый URI, замените основную функцию Cargo по умолчанию следующим образом:

    // src\main.rs
    ...
    
    fn main() -> Result<()> {
        let uri = Uri::CreateUri(h!("https://blogs.windows.com/feed"))?;
    
        Ok(())
    }
    

    Обратите внимание, что возвращаемый тип основной функции является результатом из windows::core::. Это упрощает работу, так как обычно возникают ошибки из API операционной системы (ОС). windows::core::Result помогает нам с распространением ошибок и краткой обработкой ошибок.

    Оператор вопросительного знака можно увидеть в конце строки кода. Чтобы сэкономить на вводе, мы делаем это для использования логики распространения ошибок и короткого канала Rust. Это означает, что для этого простого примера не нужно выполнять много действий по ручной обработке ошибок. Дополнительные сведения об этой функции Rust см. в разделе The ? operator for easier error handling (Использование оператора ? для упрощения обработки ошибок).

    Кроме того, обратите внимание на макрос h! из ящика окон . Мы используем это для создания ссылки HSTRING из строкового литерала Rust. API WinRT широко использует HSTRING для строковых значений.

  7. Чтобы скачать RSS-канал, мы создадим новый SyndicationClient.

    // src\main.rs
    ...
    
    fn main() -> windows::core::Result<()> {
        let uri = Uri::CreateUri(h!("https://blogs.windows.com/feed"))?;
        let client = SyndicationClient::new()?;
    
        Ok(())
    }
    

    Новая функция — конструктор Rust. Все объекты в ящике окон соответствуют соглашению Rust и называют их конструкторы новыми.

  8. Теперь мы можем использовать SyndicationClient для получения веб-канала.

    // src\main.rs
    ...
    
    fn main() -> windows::core::Result<()> {
        let uri = Uri::CreateUri(h!("https://blogs.windows.com/feed"))?;
        let client = SyndicationClient::new()?;
        let feed = client.RetrieveFeedAsync(&uri)?.get()?;
    
        Ok(())
    }
    

    Так как GetFeedAsync является асинхронным API, мы используем функцию получения блокировки, чтобы сохранить пример простым. Кроме того, можно использовать await оператор в функции для совместного async ожидания результатов. Более сложное приложение с графическим пользовательским интерфейсом часто используется async.

  9. Теперь мы можем выполнить итерацию по результирующему элементу, и давайте распечатаем только названия. Вы также увидите несколько дополнительных строк кода ниже, чтобы задать заголовок пользовательского агента, так как некоторые RSS-каналы требуют этого.

    // src\main.rs
    ...
    
    fn main() -> windows::core::Result<()> {
        let uri = Uri::CreateUri(h!("https://blogs.windows.com/feed"))?;
        let client = SyndicationClient::new()?;
    
        client.SetRequestHeader(
            h!("User-Agent"),
            h!("Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)"),
        )?;
    
        let feed = client.RetrieveFeedAsync(&uri)?.get()?;
    
        for item in feed.Items()? {
            println!("{}", item.Title()?.Text()?);
        }
    
        Ok(())
    }
    
  10. Давайте убедимся, что можно выполнить сборку и запуск, выбрав Выполнить>Запуск без отладки (или нажав клавиши CTRL+F5). Если вы видите непредвиденные сообщения, убедитесь, что вы успешно завершили учебник Hello, world! (Rust с VS Code).

    Доступны также команды Debug и Run, встроенные в текстовый редактор. Кроме того, в командной строке в папке rss_reader введите cargo run, который будет создаваться, а затем запускать программу.

    The Debug and Run commands embedded in the text editor

    Вниз в области терминала VS Code вы увидите, что Cargo успешно скачивает и компилирует контейнер окон, кэширование результатов и их использование для выполнения последующих сборок в меньшее время. Затем этот инструмент выполняет сборку примера, запускает его и отображает список заголовков записей блога.

    List of blog post titles

Это так же просто, как программировать на Rust для Windows. Однако под капотом много любви идет в создание инструментов, чтобы Rust может анализировать .winmd файлы на основе ECMA-335 (инфраструктура common Language, или CLI), а также верно соблюдать двоичный интерфейс приложения на основе COM (ABI) во время выполнения с учетом безопасности и эффективности.

Отображение окна сообщения

Мы действительно говорили, что служба Rust для Windows позволяет вызывать любой Windows API (прошлый, настоящий и будущий). Поэтому в этом разделе мы покажем несколько окон сообщений Windows.

  1. Как и для проекта RSS, в командной строке cd в папку с проектами Rust.

  2. Создайте проект с именем message_box и откройте его в VS Code:

    > cargo new message_box
    >     Created binary (application) `message_box` package
    > cd message_box
    > code .
    
  3. В VS Code откройте Cargo.tomlи добавьте зависимости Windows для этого проекта:

     # message_box\Cargo.toml
     ...
    
     [dependencies.windows]
     version = "0.43.0"
     features = [
         "Win32_Foundation",
         "Win32_UI_WindowsAndMessaging",
     ]
    
  4. Теперь откройте файл проекта src/main.rs и добавьте use объявления с новыми пространствами имен (как показано ниже). И, наконец, добавьте код для вызова функций MessageBoxA и MessageBoxW. Документация по API Windows в основном написаны с учетом C/C++, поэтому полезно сравнить документы API с документами по проекциям Rust в ящике Windows : MessageBoxA (Rust) и MessageBoxW (Rust).

    // src\main.rs
    use windows::{
        core::*,
        Win32::UI::WindowsAndMessaging::*
    };
    
    fn main() {
        unsafe {
            MessageBoxA(None, s!("Ansi"), s!("World"), MB_OK);
            MessageBoxW(None, w!("Wide"), w!("World"), MB_OK);
        }
    }
    

    Как видно, мы должны использовать эти API Win32 в блоке unsafe (см . небезопасные блоки). Кроме того, обратите внимание на макросы s! и w!, которые создают аргументы LPCSTR и LPCWSTR из строковых литералов Rust UTF-8; как мы создали HSTRING с макросом h! для rss_reader. Rust изначально является Юникодом с строками UTF-8, поэтому использование расширенных ИНТЕРФЕЙСов API Windows Юникод (W-suffix) предпочтительнее для ИНТЕРФЕЙСов API ANSI (A-suffix). Это может быть важно, если в коде используется не английский текст.

На этот раз при сборке и запуске Rust отображает два поля сообщений Windows.