Programowanie w języku Rust

Book description

Twórcy aplikacji często zapominają o kodzie systemowym, a to dzięki niemu funkcjonują system operacyjny, sterowniki, system plików czy zarządzanie pamięcią. Żadna aplikacja nie będzie działać bez poprawnego kodu systemowego. Język Rust jest dla programistów systemowych wyjątkowym narzędziem, rozwiązującym wiele znanych od dziesięcioleci problemów. Pozwala uniknąć mnóstwa powszechnie popełnianych błędów i tworzyć należytej jakości kod systemowy.

Dzięki tej książce zaczniesz kodować w języku Rust. Zrozumiesz też istotę programowania systemowego. Dowiesz się, w jaki sposób zapewnić bezpieczeństwo pamięci i wątków, a także jak sprawić, aby program był wykonywany szybko i bez błędów. Nauczysz się bezpiecznego stosowania operacji współbieżnych i poznasz zasady obsługi błędów. Przekonasz się, w jaki sposób Rust umożliwia kontrolę nad zużyciem pamięci i procesora, dodatkowo otrzymasz mnóstwo wskazówek ułatwiających tworzenie wydajnego i bezpiecznego kodu. Przewodnik jest przeznaczony głównie dla programistów systemowych, na lekturze jednak skorzystają również twórcy aplikacji, którzy dowiedzą się, jak mogą pisać lepszy, efektywniejszy i łatwiejszy w utrzymaniu kod.

W książce między innymi:

solidne wprowadzenie do języka Rust
podstawowe typy danych, a także pojęcia związane z własnością i pożyczaniem
obsługa błędów, paczki i moduły
zestawy metod i typy generyczne
domknięcia, iteratory i programowanie asynchroniczne
zaawansowane mechanizmy języka Rust

Rust: zadbasz o najwyższą jakość oprogramowania systemowego!

Table of contents

  1. Wstęp
    1. Kto powinien przeczytać tę książkę?
    2. Dlaczego napisaliśmy tę książkę?
    3. Struktura książki
    4. Konwencje stosowane w książce
    5. Użycie przykładów zawartych w książce
    6. Podziękowania
  2. Rozdział 1. Programiści systemowi mogą mieć fajne zabawki
    1. Rust zdejmuje ciężar z naszych barków
    2. Programowanie współbieżne zostaje ujarzmione
    3. A na dodatek Rust wciąż jest szybki
    4. Rust ułatwia współpracę
  3. Rozdział 2. Pierwsze spotkanie z Rustem
    1. rustup i Cargo
    2. Funkcje w języku Rust
    3. Pisanie i uruchamianie testów
    4. Obsługa argumentów wiersza poleceń
    5. Prosty serwer WWW
    6. Programowanie współbieżne
      1. Czym jest zbiór Mandelbrota?
      2. Parsowanie argumentów wiersza poleceń
      3. Odwzorowanie pikseli na liczby zespolone
      4. Rysowanie zbioru
      5. Zapis obrazu do pliku
      6. Program Mandelbrota działający współbieżnie
      7. Uruchomienie programu
      8. Przezroczyste bezpieczeństwo
    7. Narzędzia systemów plików i wiersza poleceń
      1. Interfejs wiersza poleceń
      2. Odczyt i zapis plików
      3. Znajdowanie i zastępowanie
  4. Rozdział 3. Typy proste
    1. Typy numeryczne o ustalonej długości
      1. Typy całkowite
      2. Sprawdzane, przenoszące, nasycające i przepełniające operacje arytmetyczne
      3. Typy zmiennoprzecinkowe
    2. Typ logiczny
    3. Typ znakowy
    4. Krotki
    5. Typy wskaźnikowe
      1. Referencje
      2. Pudełka
      3. Wskaźniki niechronione
    6. Tablice, wektory i podzbiory
      1. Tablice
      2. Wektory
      3. Podzbiory
    7. Typ String
      1. Literały łańcuchowe
      2. Łańcuchy bajtów
      3. Łańcuchy znaków w pamięci
      4. Typ String
      5. Podstawowe cechy typu String
      6. Inne typy znakowe
    8. Nazwy zastępcze typów
    9. Co dalej?
  5. Rozdział 4. Reguła własności i przenoszenie własności
    1. Reguła własności
    2. Przenoszenie własności
      1. Więcej operacji związanych z przeniesieniem własności
      2. Przeniesienie własności a przepływ sterowania
      3. Przeniesienie własności a struktury indeksowane
    3. Typy kopiowalne — wyjątki od reguł przenoszenia własności
    4. Rc i Arc: własność współdzielona
  6. Rozdział 5. Referencje
    1. Referencje do wartości
    2. Stosowanie referencji
      1. Referencje Rusta kontra referencje C++
      2. Referencje a operacja przypisania
      3. Referencje do referencji
      4. Porównywanie referencji
      5. Referencje nigdy nie są puste
      6. Referencje do wyrażeń
      7. Referencje do podzbiorów i zestawów metod
    3. Bezpieczeństwo referencji
      1. Referencja do zmiennej lokalnej
      2. Przekazywanie referencji jako argumentów funkcji
      3. Przekazywanie referencji do funkcji
      4. Zwracanie referencji
      5. Struktura zawierająca referencje
      6. Odrębny cykl życia
      7. Pomijanie parametrów cyklu życia
    4. Referencje współdzielone kontra mutowalne
    5. Walka ze sztormem na morzu obiektów
  7. Rozdział 6. Wyrażenia
    1. Język wyrażeń
    2. Priorytety i łączność operatorów
    3. Bloki kodu i średniki
    4. Deklaracje
    5. if i match
    6. if let
    7. Pętle
    8. Sterowanie przepływem w pętlach
    9. Wyrażenie return
    10. Analiza przepływu sterowania
    11. Wywołania funkcji i metod
    12. Pola i elementy
    13. Operatory referencji
    14. Operatory arytmetyczne, bitowe, porównania i logiczne
    15. Przypisanie
    16. Rzutowanie typów
    17. Domknięcia
    18. Co dalej?
  8. Rozdział 7. Obsługa błędów
    1. Błąd panic
      1. Odwinięcie stosu
      2. Przerywanie procesu
    2. Typ Result
      1. Przechwytywanie błędów
      2. Nazwy zastępcze typu Result
      3. Wyświetlanie informacji o błędach
      4. Propagacja błędów
      5. Jednoczesna obsługa błędów różnych typów
      6. Błędy, które nie powinny się zdarzyć
      7. Ignorowanie błędów
      8. Obsługa błędów w funkcji main()
      9. Definiowanie własnego typu błędu
      10. Co daje nam typ Result?
  9. Rozdział 8. Paczki i moduły
    1. Paczki
      1. Edycje
      2. Profile budowania
    2. Moduły
      1. Moduły zagnieżdżone
      2. Umieszczanie modułów w oddzielnych plikach
      3. Ścieżki i importy
      4. Standardowe preludium
      5. Publiczne deklaracje use
      6. Publiczne pola struktur
      7. Stałe i zmienne statyczne
    3. Zmiana programu w bibliotekę
    4. Katalog src/bin
    5. Atrybuty
    6. Testy i dokumentacja
      1. Testy integracyjne
      2. Dokumentacja
      3. Doc-testy
    7. Definiowanie zależności
      1. Wersje
      2. Cargo.lock
    8. Publikowanie paczek na stronie crates.io
    9. Obszary robocze
    10. Więcej fajnych rzeczy
  10. Rozdział 9. Struktury
    1. Struktury z polami nazywanymi
    2. Struktury z polami numerowanymi
    3. Struktury puste
    4. Reprezentacja struktur w pamięci
    5. Definiowanie metod w bloku impl
      1. Przekazywanie self z użyciem typów Box, Rc lub Arc
      2. Funkcje powiązane z typami
    6. Powiązane stałe
    7. Struktury generyczne
    8. Struktury z parametrem cyklu życia
    9. Dziedziczenie standardowych zestawów metod
    10. Zmienność wewnętrzna
  11. Rozdział 10. Typy wyliczeniowe i wzorce
    1. Typy wyliczeniowe
      1. Typy wyliczeniowe zawierające dane
      2. Typ wyliczeniowy w pamięci
      3. Większe struktury danych stosujące typy wyliczeniowe
      4. Generyczne typy wyliczeniowe
    2. Wzorce
      1. Literały, zmienne i symbole wieloznaczne
      2. Wzorce w postaci krotki lub struktury
      3. Wzorce typu tablica i fragment
      4. Wzorce z referencjami
      5. Strażniki wzorców
      6. Dopasowanie do wielu wartości
      7. Wzorce @
      8. Gdzie używamy wzorców
      9. Wypełnianie drzewa binarnego
    3. Podsumowanie
  12. Rozdział 11. Zestawy metod i typy generyczne
    1. Stosowanie zestawów metod
      1. Obiekt implementujący zestaw metod
        1. Struktura obiektu implementującego
      2. Funkcje generyczne i parametry typów
      3. Na co się zdecydować?
    2. Definiowanie i implementacja zestawów metod
      1. Metody domyślne
      2. Implementacja zestawów metod dla istniejących już typów
      3. Zestaw metod a słowo kluczowe Self
      4. Rozszerzanie zestawu metod (dziedziczenie)
      5. Funkcje powiązane z typami
    3. W pełni kwalifikowana nazwa metody
    4. Zestawy metod definiujące relacje między typami
      1. Typy powiązane
      2. Generyczny zestaw metod (czyli jak działa przeciążanie operatorów)
      3. Impl Zestaw jako typ wyniku
      4. Stałe powiązane
    5. Inżynieria wsteczna ograniczeń
    6. Zestawy metod u podstaw
  13. Rozdział 12. Przeciążanie operatorów
    1. Operatory arytmetyczne i bitowe
      1. Operatory jednoargumentowe
      2. Operatory dwuargumentowe
      3. Operatory przypisania złożonego
    2. Test równości
    3. Porównania szeregujące
    4. Interfejsy Index i IndexMut
    5. Inne operatory
  14. Rozdział 13. Interfejsy narzędziowe
    1. Drop
    2. Sized
    3. Clone
    4. Copy
    5. Deref i DerefMut
    6. Default
    7. AsRef i AsMut
    8. Borrow i BorrowMut
    9. From i Into
    10. TryFrom i TryInto
    11. ToOwned
    12. Borrow i ToOwned w działaniu
  15. Rozdział 14. Domknięcia
    1. Przechwytywanie zmiennych
      1. Domknięcia, które pożyczają wartość
      2. Domknięcia, które przejmują własność
    2. Typy funkcji i domknięć
    3. Domknięcia a wydajność
    4. Domknięcia a bezpieczeństwo
      1. Domknięcia, które zabijają
      2. FnOnce
      3. FnMut
      4. Copy i Clone dla domknięć
    5. Funkcje zwrotne
    6. Skuteczne korzystanie z domknięć
  16. Rozdział 15. Iteratory
    1. Iterator i IntoIterator
    2. Tworzenie iteratorów
      1. Metody iter i iter_mut
      2. Implementacje interfejsu IntoIterator
      3. Funkcje from_fn i successors
      4. Metody drain
      5. Inne źródła iteratorów
    3. Adaptery iteratorów
      1. map i filter
      2. filter_map i flat_map
      3. flatten
      4. take i take_while
      5. skip i skip_while
      6. peekable
      7. fuse
      8. Iteratory obustronne i rev
      9. inspect
      10. chain
      11. enumerate
      12. zip
      13. by_ref
      14. cloned i copied
      15. cycle
    4. Konsumowanie iteratorów
      1. Proste agregaty: count, sum i product
      2. max i min
      3. max_by i min_by
      4. max_by_key i min_by_key
      5. Porównywanie sekwencji elementów
      6. any i all
      7. position, rposition oraz ExactSizeIterator
      8. fold i rfold
      9. try_fold i try_rfold
      10. nth i nth_back
      11. last
      12. find, rfind i find_map
      13. Tworzenie kolekcji: collect i FromIterator
      14. Zestaw metod Extend
      15. partition
      16. for_each i try_for_each
    5. Implementacja własnych iteratorów
  17. Rozdział 16. Kolekcje
    1. Przegląd kolekcji
    2. Vec<T>
      1. Dostęp do elementów
      2. Iteracja
      3. Zwiększanie i zmniejszanie wielkości wektora
      4. Łączenie
      5. Podział
      6. Zamiana
      7. Sortowanie i wyszukiwanie
      8. Porównywanie podzbiorów
      9. Elementy losowe
      10. Reguły zapobiegające konfliktom w czasie iteracji
    3. VecDeque<T>
    4. BinaryHeap<T>
    5. HashMap<K, V> i BTreeMap<K, V>
      1. Entry
      2. Iterowanie map
    6. HashSet<T> i BTreeSet<T>
      1. Iteracja zbioru
      2. Kiedy równe wartości są różne
      3. Operacje dotyczące całego zbioru
    7. Haszowanie
    8. Niestandardowe algorytmy haszujące
    9. Kolekcje standardowe i co dalej?
  18. Rozdział 17. Tekst i łańcuchy znaków
    1. Podstawy Unicode
      1. ASCII, Latin-1 i Unicode
      2. UTF-8
      3. Kierunek tekstu
    2. Znaki (typ char)
      1. Klasyfikacja znaków
      2. Obsługa cyfr
      3. Zmiana wielkości liter
      4. Konwersja znaku do i z liczby całkowitej
    3. Typy String i str
      1. Tworzenie łańcuchów znaków
      2. Prosta inspekcja
      3. Dołączanie i wstawianie tekstu
      4. Usuwanie i zastępowanie tekstu
      5. Konwencje nazewnicze dotyczące wyszukiwania i iterowania
      6. Wyszukiwanie tekstu i wzorce
      7. Wyszukiwanie i zamiana
      8. Iterowanie tekstu
      9. Obcinanie
      10. Zmiana wielkości liter w łańcuchach
      11. Konwersja tekstu do wartości innego typu
      12. Konwersja wartości innego typu do tekstu
      13. Tworzenie referencji innego typu
      14. Tekst jako UTF-8
      15. Tworzenie tekstu na podstawie danych UTF-8
      16. Alokacja warunkowa
      17. Łańcuchy znaków jako kolekcje generyczne
    4. Formatowanie wartości
      1. Formatowanie tekstu
      2. Formatowanie liczb
      3. Formatowanie innych typów
      4. Formatowanie wartości z myślą o debugowaniu
      5. Formatowanie i debugowanie wskaźników
      6. Wiązanie argumentów za pomocą indeksu i nazwy
      7. Dynamiczne definiowanie długości i precyzji
      8. Formatowanie własnych typów
      9. Użycie języka formatowania we własnym kodzie
    5. Wyrażenia regularne
      1. Podstawowe użycie wyrażeń regularnych
      2. Wyrażenia regularne w trybie leniwym
    6. Normalizacja
      1. Rodzaje normalizacji
      2. Biblioteka unicode-normalization
  19. Rozdział 18. Operacje wejścia – wyjścia
    1. Obiekty typu reader i writer
      1. Obiekty typu reader
      2. Buforowany obiekt typu reader
      3. Przeglądanie tekstu
      4. Pobieranie tekstu
      5. Obiekty typu writer
      6. Pliki
      7. Wyszukiwanie
      8. Inne rodzaje obiektów reader i writer
      9. Dane binarne, kompresja i serializacja
    2. Pliki i katalogi
      1. OsStr i Path
      2. Metody typów Path i PathBuf
      3. Funkcje dostępu do systemu plików
      4. Odczyt zawartości katalogu
      5. Funkcje bezpośrednio związane z platformą
    3. Obsługa sieci
  20. Rozdział 19. Programowanie współbieżne
    1. Podział i łączenie wątków
      1. spawn i join
      2. Obsługa błędów w różnych wątkach
      3. Współdzielenie niemutowalnych danych przez różne wątki
      4. Rayon
      5. Zbiór Mandelbrota raz jeszcze
    2. Kanały
      1. Wysyłanie wartości
      2. Odczyt wartości
      3. Uruchomienie potoku
      4. Cechy kanałów i ich wydajność
      5. Bezpieczeństwo wątków: Send i Sync
      6. Współpraca iteratora i kanału
      7. Potoki i co dalej?
    3. Stan współdzielony mutowalny
      1. Czym jest muteks?
      2. Mutex<T>
      3. mut i Mutex
      4. Dlaczego Mutex to nie zawsze dobry pomysł?
      5. Zakleszczenie (deadlock)
      6. Zatruty muteks
      7. Kanały z wieloma nadawcami stosujące muteksy
      8. Blokady odczytu/zapisu (RwLock<T>)
      9. Zmienne warunkowe (Condvar)
      10. Typy atomowe
      11. Zmienne globalne
    4. Rust i pisanie programów wielowątkowych
  21. Rozdział 20. Programowanie asynchroniczne
    1. Od kodu synchronicznego do asynchronicznego
      1. Interfejs Future
      2. Funkcje asynchroniczne i wyrażenia await
      3. Wywoływanie funkcji asynchronicznych z kodu synchronicznego: block_on
      4. Uruchamianie asynchronicznych zadań
      5. Asynchroniczne instrukcje blokowe
      6. Tworzenie funkcji asynchronicznych z wykorzystaniem asynchronicznych instrukcji blokowych
      7. Uruchamianie zadań asynchronicznych w pulach wątków
      8. Czy operacje asynchroniczne implementują Send?
      9. Wykonywanie długotrwałych obliczeń: yield_now i spawn_local
      10. Porównanie różnych rozwiązań asynchronicznych
      11. Rzeczywisty asynchroniczny klient HTTP
    2. Asynchroniczny klient i serwer
      1. Typy błędów i wyników
      2. Protokół
      3. Pobieranie danych od użytkownika: strumienie asynchroniczne
      4. Wysyłanie pakietów
      5. Pobieranie pakietów: więcej strumieni asynchronicznych
      6. Funkcja main klienta
      7. Funkcja main serwera
      8. Obsługa połączeń z klientami: asynchroniczne muteksy
      9. Tablica grup: muteksy synchroniczne
      10. Grupy: kanały rozgłoszeniowe paczki tokio
    3. Podstawowe wartości future i wykonawcy: kiedy warto ponownie sprawdzać wartość future?
      1. Wywoływanie funkcji aktywujących: spawn_blocking
      2. Implementacja funkcji block_on
    4. Typ Pin i jego stosowanie
      1. Dwa etapy życia danych typ future
      2. Przypięte wskaźniki
      3. Zestaw metod Unpin
    5. Kiedy warto stosować kod asynchroniczny?
  22. Rozdział 21. Makra
    1. Podstawy
      1. Rozwijanie makra
      2. Niezamierzone skutki
      3. Powtórzenia
    2. Makra wbudowane
    3. Debugowanie makr
    4. Pisanie makra json!
      1. Typy składników
      2. Makra a rekurencja
      3. Makra i zestawy metod
      4. Zakres i higiena
      5. Import i eksport makr
    5. Unikanie błędów składniowych w procesie dopasowywania
    6. macro_rules! i co dalej?
  23. Rozdział 22. Kod niebezpieczny
    1. Dlaczego niebezpieczny?
    2. Bloki unsafe
    3. Przykład: wydajny typ łańcucha znaków ASCII
    4. Funkcje unsafe
    5. Kod niebezpieczny czy funkcja niebezpieczna?
    6. Działanie niezdefiniowane
    7. Zestawy metod unsafe
    8. Wskaźniki niechronione
      1. Bezpieczne tworzenie dereferencji wskaźników niechronionych
      2. Przykład: RefWithFlag
      3. Wskaźniki dopuszczające wartość pustą
      4. Rozmiary i rozmieszczanie typów
      5. Operacje arytmetyczne na wskaźnikach
      6. Wchodzenie do pamięci i wychodzenie z pamięci
      7. Przykład: GapBuffer
      8. Bezpieczeństwo błędów paniki w kodzie niebezpiecznym
    9. Ponowna interpretacja pamięci z użyciem unii
    10. Dopasowywanie unii
    11. Pożyczanie unii
  24. Rozdział 23. Funkcje obce
    1. Wyszukiwanie wspólnych reprezentacji danych
    2. Deklarowanie obcych funkcji i zmiennych
    3. Korzystanie z funkcji i bibliotek
    4. Interfejs niechroniony dla biblioteki libgit2
    5. Interfejs bezpieczny dla biblioteki libgit2
    6. Podsumowanie
      1. O autorach
      2. Kolofon

Product information

  • Title: Programowanie w języku Rust
  • Author(s): Jim Blandy
  • Release date: November 2022
  • Publisher(s): Helion
  • ISBN: 9788328395268