Rust Programming Speed And Safety For Reliable Solutions Edet

danakachile 3 views 77 slides May 18, 2025
Slide 1
Slide 1 of 77
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33
Slide 34
34
Slide 35
35
Slide 36
36
Slide 37
37
Slide 38
38
Slide 39
39
Slide 40
40
Slide 41
41
Slide 42
42
Slide 43
43
Slide 44
44
Slide 45
45
Slide 46
46
Slide 47
47
Slide 48
48
Slide 49
49
Slide 50
50
Slide 51
51
Slide 52
52
Slide 53
53
Slide 54
54
Slide 55
55
Slide 56
56
Slide 57
57
Slide 58
58
Slide 59
59
Slide 60
60
Slide 61
61
Slide 62
62
Slide 63
63
Slide 64
64
Slide 65
65
Slide 66
66
Slide 67
67
Slide 68
68
Slide 69
69
Slide 70
70
Slide 71
71
Slide 72
72
Slide 73
73
Slide 74
74
Slide 75
75
Slide 76
76
Slide 77
77

About This Presentation

Rust Programming Speed And Safety For Reliable Solutions Edet
Rust Programming Speed And Safety For Reliable Solutions Edet
Rust Programming Speed And Safety For Reliable Solutions Edet


Slide Content

Rust Programming Speed And Safety For Reliable
Solutions Edet download
https://ebookbell.com/product/rust-programming-speed-and-safety-
for-reliable-solutions-edet-57358020
Explore and download more ebooks at ebookbell.com

Here are some recommended products that we believe you will be
interested in. You can click the link to download.
Rust Programming Cookbook Explore The Latest Features Of Rust 2018 For
Building Fast And Secure Apps Claus Matzinger
https://ebookbell.com/product/rust-programming-cookbook-explore-the-
latest-features-of-rust-2018-for-building-fast-and-secure-apps-claus-
matzinger-23664678
Rust Programming By Example Antoni Boucherdaniel Duranteguillaume
Gomezsebastian Drge
https://ebookbell.com/product/rust-programming-by-example-antoni-
boucherdaniel-duranteguillaume-gomezsebastian-drge-11338932
Rust Programming By Example Enter The World Of Rust By Building
Engaging Concurrent Reactive And Robust Applications Antoni Boucher
Guillaume Gomez
https://ebookbell.com/product/rust-programming-by-example-enter-the-
world-of-rust-by-building-engaging-concurrent-reactive-and-robust-
applications-antoni-boucher-guillaume-gomez-62311094
Rust Programming For Your First Finance Job A Comprehensive Guide
Publishing
https://ebookbell.com/product/rust-programming-for-your-first-finance-
job-a-comprehensive-guide-publishing-59785544

Rust Programming By Example Guillaume Gomez
https://ebookbell.com/product/rust-programming-by-example-guillaume-
gomez-57017404
Rust Web Programming A Handson Guide To Developing Fast And Secure Web
Apps With The Rust Programming Language 1st Edition Maxwell Flitton
https://ebookbell.com/product/rust-web-programming-a-handson-guide-to-
developing-fast-and-secure-web-apps-with-the-rust-programming-
language-1st-edition-maxwell-flitton-52852756
Learn Rust Programming 1st Edition Claus Matzinger
https://ebookbell.com/product/learn-rust-programming-1st-edition-
claus-matzinger-49188462
The Rust Programming Language 2nd Edition Second Converted Steve
Klabnik Carol Nichols
https://ebookbell.com/product/the-rust-programming-language-2nd-
edition-second-converted-steve-klabnik-carol-nichols-49465120
The Rust Programming Language Covers Rust 2018 Illustrated Steve
Klabnik
https://ebookbell.com/product/the-rust-programming-language-covers-
rust-2018-illustrated-steve-klabnik-50194554

[
Rust Programming: Speed and Safety for Reliable
Solutions
By Theophilus Edet
Theophilus Edet
[email protected]
facebook.com/theoedet
twitter.com/TheophilusEdet
Instagram.com/edettheophilus

Copyright © 2024 Theophilus Edet All rights reserved.
No part of this publication may be reproduced, distributed, or transmitted in any form or by any
means, including photocopying, recording, or other electronic or mechanical methods, without the
prior written permission of the publisher, except in the case of brief quotations embodied in reviews
and certain other non-commercial uses permitted by copyright law.

Table of Contents
Preface
[Book Title]
Module 1: Introduction to Rust: Understanding the Basics
Overview of Rust: A Comprehensive Introduction
Setting Up Rust Environment: Configuration and Setup Guide
Variables and Data Types in Rust: Exploring Rust's Type System
Comments and Documentation: Writing Effective Code Documentation
Module 2: Basic Syntax and Control Flow: Mastering Fundamentals
Functions in Rust: Defining and Utilizing Functions
Control Flow: Conditions and Loops: Managing Program Flow
Error Handling: Strategies for Error Detection and Resolution
Scope and Shadowing: Managing Variable Scopes in Rust
Module 3: Working with Collections: Handling Data Structures
Arrays and Vectors: Utilizing Array and Vector Data Structures
Slices: Efficiently Working with Subsets of Data
Strings: Manipulating and Formatting Text Data
Tuples: Combining Heterogeneous Data in Rust
Module 4: Advanced Control Flow: Refining Flow Control
Pattern Matching: Advanced Data Extraction Techniques
Advanced Looping Techniques: Iterating with Finesse
Early Returns: Optimizing Control Flow Patterns
Exiting Programs: Graceful Program Termination Strategies
Module 5: Ownership and Borrowing: Understanding Memory Management
Ownership Rules: Managing Memory Allocation in Rust
References and Borrowing: Sharing Data Safely
Mutable References: Allowing Mutability with Caution
Lifetimes: Ensuring Safe Resource Management
Module 6: Structs and Enums: Structuring Data
Defining Structs: Creating Custom Data Types
Implementing Methods for Structs: Adding Functionality to Structs
Enums and Pattern Matching: Defining and Using Enumerations
Associated Functions and Methods: Utilizing Methods on Enums and Structs
Module 7: Error Handling and Result: Handling Errors Gracefully
Handling Errors with Result: Effective Error Propagation Techniques
Unwrapping and Expecting Results: Safely Unpacking Results
Propagating Errors: Passing Errors Up the Call Stack
Custom Error Types: Creating Custom Error Types in Rust
Module 8: Option and Result: Handling Optional Values
Working with Option: Dealing with Absent Values
Combining Option and Result: Effective Error Handling with Option and Result
Chaining Result Operations: Combining Multiple Result Operations
Error Handling Patterns: Best Practices for Error Handling
Module 9: Generics: Making Code More Flexible
Introduction to Generics: Understanding Rust's Generics
Implementing Functions with Generics: Writing Generic Functions with Rust
Implementing Structs with Generics: Creating Generic Data Structures in Rust
Traits and Generic Types: Constraining Generics with Traits and Associated Types
Module 10: Concurrency: Managing Concurrent Operations
Threads: Concurrent Execution with Threads

Message Passing: Inter-Thread Communication
Shared State Concurrency: Synchronizing Access to Shared Data
Using Mutexes and Arcs: Ensuring Thread Safety with Mutexes and Arcs
Module 11: Traits: Defining Common Behavior
Defining and Using Traits: Implementing Trait Interfaces
Implementing Traits for Custom Types: Extending Functionality with Traits
Trait Bounds: Constraining Generics with Traits
Trait Objects: Working with Dynamic Dispatch
Module 12: Advanced Traits: Enhancing Trait Functionality
Associated Types: Type Abstraction with Associated Types
Default Implementations: Providing Default Trait Implementations
Implementing Clone and Copy Traits: Duplicating Values with Clone and Copy
Using Traits for Error Handling: Error Reporting with Traits
Module 13: Macros: Extending Rust's Syntax
Introduction to Macros: Understanding Rust Macros
Writing Macros with macro_rules!: Simple Macro Creation
Procedural Macros: Customizing Syntax with Procedural Macros
Custom Derive Macros: Deriving Traits with Macros
Module 14: Modules and Packages: Organizing Rust Code
Organizing Code with Modules: Structuring Code for Maintainability
Creating and Using Packages: Packaging Code for Distribution
Crates.io and Dependency Management: Managing Dependencies with Cargo
Module Visibility and Privacy: Controlling Access to Module Contents
Module 15: File I/O: Working with Files
Reading Files: Reading Data from Files
Writing Files: Writing Data to Files
Error Handling in File I/O: Handling Errors in File Operations
Working with Paths: Manipulating File Paths in Rust
Module 16: Testing: Ensuring Code Quality
Writing Tests in Rust: Creating and Running Tests
Running Tests with Cargo: Automating Testing with Cargo
Integration Tests vs. Unit Tests: Choosing the Right Testing Approach
Test Organization and Best Practices: Structuring Test Suites for Maintainability
Module 17: Documentation: Documenting Rust Code
Writing Documentation Comments: Documenting Code for Clarity
Generating Documentation with Cargo: Generating Documentation with Cargo
Documenting Code Examples: Providing Examples in Documentation
Publishing Documentation to Docs.rs: Sharing Documentation with the Rust Community
Module 18: Advanced Ownership: Exploring Ownership Patterns
Rc and RefCell: Shared Ownership with Rc and Interior Mutability with RefCell
Interior Mutability: Mutating Interior Data Immobilized by Borrowing
Copy vs. Clone: Understanding Copy and Clone Traits
Dropping and the Drop Trait: Managing Resource Cleanup with Drop Trait
Module 19: Advanced Enums: Leveraging Enumerations
Enum Variants with Data: Defining Enums with Associated Data
Match Guards: Adding Conditions to Match Arms
Combining Enums with Structs: Utilizing Enums with Structs
Recursive Enums: Defining Enums that Refer to Themselves
Module 20: Advanced Patterns: Mastering Pattern Matching
Advanced Pattern Matching: Complex Pattern Matching Techniques
Deconstructing Structs and Enums: Extracting Data from Complex Types
Refutable and Irrefutable Patterns: Understanding Patterns that May Fail
Match Ergonomics: Writing Concise and Readable Pattern Matching Code
Module 21: Advanced Generics: Pushing the Limits of Generics
Higher-Order Functions: Functions that Operate on Functions

Generic Lifetimes: Specifying Lifetimes in Generic Types
Phantom Types: Using Phantom Types for Compile-Time Constraints
Variadic Generic Functions: Functions with a Variable Number of Arguments
Module 22: Advanced Traits and Associated Types: Expanding Trait Capabilities
Advanced Trait Bounds: Constraining Generics with Complex Trait Bounds
Type Alias Associated Types: Defining Associated Types with Type Aliases
Generic Associated Types: Defining Associated Types in Generic Contexts
Conditional Trait Implementations: Implementing Traits Conditionally Based on Types
Module 23: Rust Ecosystem: Navigating Rust's Landscape
Exploring the Rust Ecosystem: Overview of Rust Libraries and Tools
Popular Rust Libraries and Frameworks: Overview of Popular Rust Libraries and Frameworks
Contributing to Open Source Rust Projects: Getting Involved in the Rust Community
Rust Community and Resources: Finding Support and Learning Resources in the Rust Community
Module 24: Web Development with Rust: Building Web Applications
Introduction to Web Development in Rust: Overview of Rust's Web Development Capabilities
Web Frameworks: Rocket, Actix, Warp: Exploring Popular Rust Web Frameworks
Working with Databases: Interfacing with Databases in Rust Web Applications
Deploying Rust Web Applications: Deploying Rust Web Apps to Production Environments
Module 25: GUI Development with Rust: Creating Desktop Applications
Overview of GUI Development in Rust: Introduction to Rust's GUI Development Landscape
GUI Frameworks: Gtk-rs, Druid, Iced: Exploring Rust GUI Frameworks
Building Desktop Applications: Developing Cross-Platform Desktop Apps in Rust
Cross-Platform GUI Development: Creating GUIs for Multiple Platforms with Rust
Module 26: Game Development with Rust: Crafting Games
Rust for Game Development: Introduction to Rust's Role in Game Development
Game Engines: Amethyst, ggez, Bevy: Overview of Rust Game Engines
Graphics Programming with Rust: Leveraging Rust for Graphics Development
Deploying Rust Games: Distributing Games Developed in Rust
Module 27: Embedded Rust: Programming for Embedded Systems
Introduction to Embedded Systems: Overview of Embedded Systems Development
Working with Microcontrollers: Programming Microcontrollers with Rust
Rust for IoT Applications: Building IoT Solutions with Rust
Real-Time Operating Systems in Rust: Developing Real-Time Systems with Rust
Module 28: Parallel and Distributed Computing: Scaling with Rust
Parallelism in Rust: Harnessing Parallel Processing in Rust
Distributed Computing with Rust: Building Distributed Systems with Rust
Message Passing and Actor Model: Implementing Message Passing in Rust
Rust for High-Performance Computing: Leveraging Rust for High-Performance Computing Tasks
Module 29: Machine Learning and AI with Rust: Exploring AI Capabilities
Rust for Machine Learning: Overview of Rust's Role in Machine Learning
Using Rust with TensorFlow and PyTorch: Integrating Rust with Popular ML Frameworks
Reinforcement Learning in Rust: Implementing RL Algorithms in Rust
Building AI Applications with Rust: Developing AI Applications in Rust
Module 30: Conclusion and Next Steps: Wrapping Up and Looking Forward
Recap of Rust Features and Concepts: Summary of Key Rust Concepts Covered
Real-world Rust Applications: Examples of Real-world Applications Built with Rust
Continuing Your Rust Journey: Resources for Further Learning and Development
Future of Rust and Emerging Trends: Looking Ahead to the Future of Rust Programming
Review Request
Embark on a Journey of ICT Mastery with CompreQuest Books

Preface
Welcome to Rust Programming: Speed and Safety for Reliable
Solutions! In this book, we embark on a journey to explore the
power and elegance of the Rust programming language. This
guide is crafted to equip you with the knowledge and skills necessary to
harness Rust's capabilities for building robust and efficient software
solutions.
Unveiling Rust's Components
Rust's design philosophy revolves around speed, safety, and reliability.
Throughout this book, we delve into the fundamental components of Rust
and how they contribute to achieving these objectives:
1. Variables: Rust's strong typing system ensures the safety of
variable assignments, preventing common pitfalls like null pointer
dereferencing and memory leaks.
2. Functions: Rust supports functions as first-class citizens, allowing
for modular code organization and reuse. We explore how
functions are defined, invoked, and utilized in Rust programs.
3. Conditions: Rust provides robust support for conditionals,
including if-else statements and pattern matching, enabling
developers to express complex logic with clarity and conciseness.
4. Collections: Rust offers a rich set of data structures, including
arrays, vectors, slices, and strings, for efficiently handling and
manipulating collections of data.
5. Loops: Rust's loop constructs, such as for, while, and loop, enable
iterative control flow, facilitating tasks like iterating over
collections or performing repetitive operations.
6. Comments: Effective code documentation is essential for
collaborative development. Rust encourages the use of comments
and documentation annotations to enhance code clarity and
maintainability.

7. Enums: Enums in Rust enable developers to define custom data
types with distinct variants, enhancing code expressiveness and
type safety.
8. Classes and Accessors: Rust follows a different paradigm than
traditional object-oriented languages like Java or C++, opting for
structs and traits instead of classes. We explore how Rust achieves
encapsulation and abstraction through these constructs.
9. Scope: Rust's ownership and borrowing system governs variable
lifetimes and memory management, ensuring safe and efficient
resource utilization within defined scopes.
Applications of Rust
Rust's versatility extends across a wide range of applications and domains:
Systems Programming: Rust is well-suited for low-level systems
programming, where performance, safety, and reliability are
paramount.
Web Development: With frameworks like Rocket and Actix Web,
Rust is gaining traction in web development, offering high
performance and security for backend services and APIs.
Game Development: Rust's performance and safety features make
it an attractive choice for game development, enabling developers
to create immersive and efficient gaming experiences.
Embedded Systems: Rust's focus on safety and efficiency makes it
ideal for embedded systems development, powering devices
ranging from IoT sensors to autonomous vehicles.
Programming Models and Paradigms
Rust supports various programming models and paradigms, including
imperative, functional, and concurrent programming. Its flexible type
system and expressive syntax enable developers to embrace different
programming styles while maintaining performance and safety.
Pedagogical Style of Presentation

Throughout this book, we adopt a hands-on approach to learning Rust,
combining theoretical concepts with practical examples. Each of the
exhaustive 30 modules is designed to build upon the previous ones,
gradually introducing new concepts and techniques in a structured and
intuitive manner.
Rust Programming: Speed and Safety for Reliable Solutions is more than
just a book—it's a comprehensive guide and companion for your journey
into the world of Rust programming. Whether you're a seasoned developer
or a newcomer to the language, this book is designed to empower you with
the knowledge and skills needed to become proficient in Rust and build
software solutions that are fast, secure, and reliable. Let's embark on this
exciting adventure together!
Theophilus Edet

Rust Programming: Speed and Safety for
Reliable Solutions
Rust Programming: Speed and Safety for Reliable Solutions is a
comprehensive guide to learning and mastering the Rust programming
language. This book serves as a roadmap for developers seeking to harness
Rust's unique features and capabilities for building fast, secure, and reliable
software solutions.
Overview of Rust Programming
Rust, developed by Mozilla Research, is a modern systems programming
language that prioritizes performance, safety, and concurrency. Since its
official release in 2015, Rust has gained widespread popularity among
developers for its ability to combine low-level control with high-level safety
features. Rust's design philosophy aims to address common pitfalls found in
other languages, making it an excellent choice for a wide range of
applications across various domains.
Applications of Rust
Rust's versatility makes it suitable for a variety of applications, including:
1. Systems Programming: Rust is often used for developing low-
level system components, such as operating systems, device
drivers, and embedded firmware. Its memory safety guarantees and
zero-cost abstractions make it well-suited for building high-
performance, reliable systems software.
2. Web Development: Rust's performance and safety features have
led to its adoption in web development, particularly for building
backend services, APIs, and serverless applications. Frameworks
like Rocket and Actix Web provide developers with the tools they
need to create fast, scalable web applications with Rust.
3. Game Development: Rust's performance and expressive type
system make it well-suited for game development. Game engines
like Amethyst leverage Rust's concurrency features to build

immersive, multiplatform games with high performance and
reliability.
4. Embedded Systems: Rust's focus on safety and low-level
programming makes it an ideal choice for embedded systems
development. Projects like Tock OS and Rust Embedded provide
developers with the tools and libraries needed to build secure,
reliable firmware for microcontrollers and IoT devices.
Programming Models and Paradigms Supported by Rust
Rust supports a variety of programming models and paradigms, including:
1. Imperative Programming: Rust supports imperative
programming paradigms, allowing developers to express
algorithms and control flow using mutable state and explicit
control structures like loops and conditionals.
2. Functional Programming: Rust embraces functional
programming concepts, such as immutability, higher-order
functions, and pattern matching. Functional programming
techniques can be used to write concise, expressive code that is
easier to reason about and test.
3. Concurrency and Parallelism: Rust provides powerful
abstractions for writing concurrent and parallel code, including
lightweight threads, message passing, and data parallelism. The
ownership and borrowing system ensures safe concurrent access to
data without the need for locks or mutexes.
4. Object-Oriented Programming: While Rust is not a pure object-
oriented language like Java or C++, it supports object-oriented
programming (OOP) concepts through the use of structs, traits, and
associated functions. Rust's trait system allows for code reuse and
polymorphism without sacrificing performance or safety.
5. Generic Programming: Rust's support for generics allows
developers to write code that is generic over types, enabling code
reuse and flexibility without sacrificing performance or safety.

Generics are extensively used in Rust's standard library and
ecosystem to provide reusable abstractions and data structures.
In summary, Rust Programming: Speed and Safety for Reliable Solutions
introduces readers to the Rust programming language and its applications
across various domains. By exploring Rust's design philosophy, features,
and programming models, developers can gain a deeper understanding of
how to leverage Rust's strengths for building fast, secure, and reliable
software solutions.

Module 1:
Introduction to Rust: Understanding the
Basics
Rust, a programming language developed by Mozilla, has been gaining
traction in recent years due to its unique combination of performance,
safety, and concurrency. In this module, we embark on a journey to explore
the fundamental concepts of Rust, laying the groundwork for mastering this
powerful language.
Overview of Rust: A Comprehensive Introduction
At its core, Rust is designed to address the challenges faced by systems
programmers, offering a modern alternative to languages like C and C++.
One of Rust's defining features is its emphasis on memory safety without
sacrificing performance. Unlike languages that rely on garbage collection,
Rust employs a system of ownership, borrowing, and lifetimes to ensure
memory safety at compile time.
Rust's design philosophy revolves around three key principles: safety,
speed, and concurrency. By enforcing strict rules at compile time, Rust
eliminates entire classes of bugs that are common in other languages, such
as null pointer dereferences and data races. Additionally, Rust's zero-cost
abstractions and low-level control make it well-suited for building high-
performance software.
Setting Up Rust Environment: Configuration and Setup Guide
Before diving into Rust programming, it's essential to set up the
development environment. Thankfully, Rust's tooling ecosystem, centered
around the Cargo package manager, makes this process straightforward. To
get started, simply install Rust using the official installer, which includes

the Rust compiler (rustc), package manager (Cargo), and other essential
tools.
Once Rust is installed, configuring your development environment involves
selecting a text editor or integrated development environment (IDE) that
supports Rust syntax highlighting and integration with Cargo. Popular
choices include Visual Studio Code with the Rust extension, IntelliJ IDEA
with the Rust plugin, and Emacs with the Rust mode.
With your environment configured, creating a new Rust project is as simple
as running cargo new project_name. This command sets up a new
directory structure with a default project layout, including a src directory
for source code and a Cargo.toml file for managing dependencies and
project metadata.
Variables and Data Types in Rust: Exploring Rust's Type System
Rust's type system is both powerful and expressive, allowing developers to
write code that is both safe and efficient. At the heart of Rust's type system
are its primitive data types, which include integers, floating-point numbers,
booleans, characters, and strings. Unlike dynamically typed languages, Rust
performs type checking at compile time, catching type-related errors before
they can manifest at runtime.
In addition to primitive data types, Rust supports compound types such as
arrays, slices, tuples, and structs. Arrays are fixed-size collections of
elements with a homogeneous type, while slices are dynamically sized
views into contiguous memory. Tuples, on the other hand, are
heterogeneous collections of fixed-size elements, making them ideal for
representing ad-hoc data structures.
Rust's type system also includes support for generics, allowing developers
to write code that is generic over types. This enables the creation of
reusable components that work with any data type, enhancing code
modularity and reducing duplication. Traits, which define behavior shared
across types, further extend Rust's type system by enabling ad-hoc
polymorphism and code reuse.
Comments and Documentation: Writing Effective Code Documentation

Documenting code is an essential aspect of software development, and Rust
provides built-in support for writing effective documentation. Rust's
documentation system is based on Markdown syntax, making it easy to
write and maintain documentation alongside your code. By annotating
functions, types, and modules with doc comments, you can generate
comprehensive API documentation using the cargo doc command.
In addition to API documentation, Rust's documentation system supports
code examples, allowing developers to provide usage examples alongside
function signatures and module documentation. This promotes code literacy
and helps users understand how to use your code in real-world scenarios.
Additionally, Rust's documentation generator can publish documentation to
the web via platforms like docs.rs, making it accessible to the broader Rust
community.
This module provides a comprehensive introduction to Rust, covering its
core principles, development environment setup, type system, and
documentation features. By mastering these fundamentals, you'll be well-
equipped to tackle more advanced topics in Rust programming and build
reliable, high-performance software.
Overview of Rust: A Comprehensive Introduction
Rust, often described as a systems programming language, combines
the performance of low-level languages like C and C++ with the
safety and modern features of high-level languages like Python and
JavaScript. This comprehensive introduction provides an overview of
Rust's design philosophy, core features, and ecosystem, setting the
stage for a deeper exploration of its capabilities.
Design Philosophy: Balancing Performance and Safety
At its core, Rust aims to provide a language that empowers
developers to write fast and reliable code without compromising on
safety. Its design philosophy revolves around three key principles:
performance, safety, and expressiveness. Rust achieves this balance
by leveraging a strict type system, ownership model, and concurrency
primitives to ensure memory safety and prevent common
programming errors.

fn main() {
let mut v = vec![1, 2, 3];
let first = v.get(0).unwrap(); // Safe access
v.push(4); // Error: mutable borrow occurs here
}
In the example above, attempting to push a new element into a vector
while holding an immutable reference to its first element results in a
compilation error. This demonstrates Rust's commitment to safety by
preventing potential data races and memory corruption.
Core Features: Ownership, Borrowing, and Lifetimes
Rust's ownership system lies at the heart of its safety guarantees,
ensuring that memory is managed efficiently without the need for
garbage collection. By tracking the ownership of values and
enforcing strict rules at compile time, Rust prevents common
memory-related bugs such as use-after-free errors and double frees.
fn main() {
let s1 = String::from("hello");
let s2 = s1; // Move ownership to s2
println!("{}", s1); // Error: value moved here
}
In this example, ownership of the String value is transferred from s1
to s2 via a move operation, rendering s1 invalid afterward. This
demonstrates Rust's ownership semantics in action, preventing the
use of a value after it has been moved.
Ecosystem: Growing and Vibrant Community
Rust's ecosystem is characterized by a vibrant and growing
community of developers, libraries, and tools. From web
development and systems programming to machine learning and
embedded systems, Rust is used across a diverse range of domains
and industries. The Rust community fosters collaboration, innovation,
and inclusivity, making it an exciting and welcoming environment for
developers of all backgrounds.
use reqwest::blocking::get;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let body = get("https://www.rust-lang.org")?.text()?;

println!("{}", body);
Ok(())
}
In this example, the reqwest crate is used to make a synchronous
HTTP request and fetch the contents of the Rust programming
language website. This showcases Rust's ecosystem of third-party
libraries and tools, enabling developers to build a wide range of
applications with ease.
This comprehensive introduction provides an overview of Rust's
design philosophy, core features, and ecosystem. By understanding
Rust's commitment to performance, safety, and expressiveness,
developers can leverage its unique capabilities to build fast, reliable,
and maintainable software across various domains and industries.
Setting Up Rust Environment: Configuration and Setup
Guide
Setting up the Rust environment is the initial step in starting a Rust
project. This section provides a comprehensive guide to configuring
and setting up Rust on various platforms, including installation
instructions, package management, and tooling setup. By following
this guide, developers can quickly set up their development
environment and begin writing Rust code.
Installation Instructions: Getting Rust Up and Running
The first step in setting up the Rust environment is to install the Rust
compiler and toolchain. Rust provides official installation instructions
for various operating systems, including Windows, macOS, and
Linux. Developers can choose between installing Rust via Rustup,
the official Rust toolchain installer, or using system package
managers where available.
# Install Rust via Rustup (Recommended)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
This command installs Rustup, which manages Rust installations and
updates, and sets up the latest stable version of the Rust compiler and
associated tools. Rustup also allows developers to manage multiple
Rust toolchains and easily switch between them for different projects.

Package Management: Using Cargo for Dependency
Management
Once Rust is installed, developers can use Cargo, Rust's package
manager and build tool, to create, build, and manage Rust projects.
Cargo simplifies dependency management by automatically fetching
and building project dependencies from the official crates.io registry.
# Create a new Rust project
cargo new my_project
cd my_project
# Add dependencies to Cargo.toml
[dependencies]
rand = "0.8.4"
In this example, a new Rust project is created using Cargo, and the
rand crate is added as a dependency in the project's Cargo.toml file.
When the project is built or run using Cargo, it automatically fetches
and builds the rand crate and its dependencies.
Tooling Setup: Configuring Editors and IDEs for Rust
Development
Configuring editors and IDEs for Rust development enhances the
developer experience by providing features such as syntax
highlighting, code completion, and project navigation. Rust has
excellent support for popular editors and IDEs, including Visual
Studio Code.
# Install Rust extension for Visual Studio Code
code --install-extension rust-lang.rust
In this example, the Rust extension for Visual Studio Code is
installed using the command-line interface. This extension provides a
rich set of features for Rust development, including syntax
highlighting, code formatting, and integrated terminal support.
Similar extensions and plugins are available for other editors and
IDEs, allowing developers to choose the tools that best suit their
workflow.

This section provides a comprehensive guide to setting up the Rust
environment, including installation instructions, package
management with Cargo, and tooling setup for popular editors and
IDEs such as Visual Studio Code. By following these steps,
developers can quickly configure their development environment and
start writing Rust code with confidence.
Variables and Data Types in Rust: Exploring Rust's Type
System
Variables and data types form the foundation of any programming
language, and Rust is no exception. This section explores Rust's type
system, covering basic data types, variable declaration, and type
inference. Understanding variables and data types in Rust is crucial
for writing safe and efficient code.
Variable Declaration: Mutable and Immutable Bindings
In Rust, variables are immutable by default, meaning their values
cannot be changed once set. Developers can declare mutable
variables by using the mut keyword, allowing them to modify the
variable's value after its initial assignment.
fn main() {
let x = 5; // Immutable binding
let mut y = 10; // Mutable binding
y = 15; // Modify mutable variable
println!("x: {}, y: {}", x, y);
}
In this example, x is immutable, and attempting to reassign its value
results in a compilation error. On the other hand, y is mutable,
allowing its value to be changed after declaration.
Basic Data Types: Numeric, Boolean, and Character Types
Rust provides a variety of basic data types, including integers,
floating-point numbers, booleans, and characters. These types are
used to represent different kinds of data and perform various
operations in Rust programs.
fn main() {
let integer: i32 = 42;

let float: f64 = 3.14;
let boolean: bool = true;
let character: char = 'a';
println!("Integer: {}, Float: {}, Boolean: {}, Character: {}", integer, float, boolean,
character);
}
In this example, variables of different data types are declared and
initialized with values. Rust's strong typing ensures type safety and
prevents unintended type conversions, enhancing the reliability of
Rust programs.
Type Inference: Letting the Compiler Deduce Types
Rust features type inference, allowing developers to omit explicit
type annotations in many cases. The compiler infers the types of
variables based on their usage, reducing verbosity while maintaining
type safety.
fn main() {
let x = 42; // Compiler infers type i32
let y = 3.14; // Compiler infers type f64
let z = true; // Compiler infers type bool
println!("x: {}, y: {}, z: {}", x, y, z);
}
In this example, type annotations are omitted, and the compiler
deduces the types of variables x, y, and z based on their assigned
values.
Understanding variables and data types in Rust lays the groundwork
for writing expressive and reliable code. By leveraging Rust's type
system, developers can ensure type safety, prevent common
programming errors, and build robust software systems.
Comments and Documentation: Writing Effective Code
Documentation
Comments and documentation play a crucial role in making code
understandable and maintainable. This section explores best practices
for writing comments and documentation in Rust, covering inline
comments, doc comments, and generating documentation with Rust's
built-in tools.

Inline Comments: Adding Context to Code
Inline comments provide context and explanations within the code
itself, helping other developers understand the purpose and
functionality of specific code blocks. Rust supports both single-line
and multi-line comments, allowing developers to annotate their code
effectively.
fn main() {
// Calculate the sum of two numbers
let a = 5;
let b = 10;
let sum = a + b; // Store the result in the 'sum' variable
println!("The sum of {} and {} is {}", a, b, sum);
}
In this example, inline comments are used to clarify the purpose of
variable declarations and the calculation of the sum.
Doc Comments: Documenting Rust Code
Doc comments, also known as documentation comments, are used to
document Rust code and generate API documentation. Doc
comments start with /// for documenting items like functions, structs,
enums, and modules. Rust's documentation system, powered by
Rustdoc, automatically generates HTML documentation from doc
comments.
/// Calculates the sum of two numbers.
///
/// # Arguments
///
/// * `a` - The first number.
/// * `b` - The second number.
///
/// # Returns
///
/// The sum of `a` and `b`.
fn sum(a: i32, b: i32) -> i32 {
a + b
}
In this example, a doc comment is used to document a function
named sum, describing its purpose, arguments, and return value.
When Rustdoc generates documentation, this information is included

in the generated HTML documentation, making it easy for users to
understand how to use the function.
Generating Documentation: Rustdoc and Cargo
Rustdoc is a tool that comes bundled with the Rust compiler and is
used to generate documentation from doc comments in Rust code. By
running cargo doc, developers can generate HTML documentation
for their Rust projects, including all public items and their associated
documentation comments.
# Generate HTML documentation for the project
cargo doc –open
In this example, running cargo doc --open generates HTML
documentation for the current Rust project and opens it in the default
web browser. Developers can then browse the generated
documentation to understand how to use the project's API and
explore its functionality.
Effective use of comments and documentation in Rust enhances code
readability, maintainability, and usability. By following best practices
for writing comments and documentation, developers can create clear
and comprehensive documentation for their Rust projects, making
them more accessible to users and contributors.

Module 2:
Basic Syntax and Control Flow:
Mastering Fundamentals
In this module, we delve deeper into Rust's syntax and explore essential
concepts related to control flow. Understanding these fundamental building
blocks is crucial for writing clear, concise, and efficient Rust code.
Functions in Rust: Defining and Utilizing Functions
Functions are the cornerstone of modular programming, enabling code
reuse and organization. In Rust, functions are defined using the fn keyword
followed by the function name, parameters, return type (if any), and the
function body enclosed in curly braces. Rust supports both function
definitions with and without return values.
One of Rust's distinctive features is its support for pattern matching in
function parameters. This allows developers to write concise and expressive
code by matching against different patterns of input values. Additionally,
Rust functions can have multiple parameters, default parameter values, and
variable-length argument lists using the ... syntax.
Control Flow: Conditions and Loops: Managing Program Flow
Control flow mechanisms, such as conditions and loops, enable developers
to dictate the flow of execution in a program. In Rust, conditional
expressions are defined using the if, else if, and else keywords. Rust's
pattern matching capabilities extend to conditions, allowing for powerful
and readable code constructs.
Rust provides several loop constructs, including loop, while, and for. The
loop keyword creates an infinite loop, which can be exited using the break
statement. The while loop repeats a block of code while a condition is true,
and the for loop iterates over elements of a collection.

Error Handling: Strategies for Error Detection and Resolution
Error handling is a critical aspect of writing robust and reliable software.
Rust's approach to error handling revolves around the Result and Option
types, which represent computations that may succeed or fail. By
propagating errors using Result, Rust ensures that error conditions are
explicitly handled by the caller.
Rust's error handling paradigm encourages developers to handle errors at
the point of occurrence using pattern matching or the ? operator, which
short-circuits the function and returns the error if encountered. Additionally,
Rust supports custom error types, enabling developers to define domain-
specific error conditions and behaviors.
Scope and Shadowing: Managing Variable Scopes in Rust
Understanding variable scopes and lifetimes is crucial for writing memory-
safe Rust code. Rust employs a system of lexical scoping, where variables
are valid within a specific lexical scope. Variable shadowing, a feature
unique to Rust, allows developers to redeclare variables within the same
scope, effectively hiding the outer variable.
Rust's ownership model ensures that variables are deallocated when they go
out of scope, preventing memory leaks and dangling references.
Additionally, Rust's borrow checker enforces strict rules around mutable
and immutable references, preventing data races and other common
concurrency bugs.
This module equips you with essential skills for mastering Rust's basic
syntax and control flow constructs. By understanding functions, conditions,
loops, and error handling mechanisms, you'll be well-prepared to write
clear, concise, and reliable Rust code.
Functions in Rust: Defining and Utilizing Functions
Functions are fundamental building blocks of any programming
language, allowing developers to encapsulate logic and reuse it
throughout their code. This section delves into defining and utilizing
functions in Rust, covering function syntax, parameter passing, return
values, and function visibility.

Function Syntax: Declaring Functions in Rust
In Rust, functions are declared using the fn keyword followed by the
function name and optional parameters and return type. Function
bodies contain the code to be executed when the function is called.
fn greet(name: &str) {
println!("Hello, {}!", name);
}
fn main() {
greet("world");
}
In this example, a function named greet is defined, which takes a
single parameter name of type &str (a string slice) and prints a
greeting message.
Parameter Passing: Passing Values to Functions
Rust supports passing parameters to functions by value or by
reference. By default, parameters are passed by immutable reference,
but developers can use the mut keyword to declare mutable
references if needed.
fn double(x: i32) -> i32 {
x * 2
}
fn main() {
let num = 5;
let doubled = double(num);
println!("{} doubled is {}", num, doubled);
}
In this example, a function named double takes a single parameter x
of type i32 (an integer) and returns twice the value of x.
Return Values: Returning Results from Functions
Functions in Rust can return values using the return keyword
followed by the expression or value to be returned. Alternatively, the
last expression in the function body is implicitly returned without
using the return keyword.

fn add(a: i32, b: i32) -> i32 {
a + b
}
fn main() {
let result = add(3, 4);
println!("The sum is {}", result);
}
In this example, a function named add takes two parameters a and b
of type i32 and returns their sum as an i32 value.
Function Visibility: Controlling Access to Functions
By default, functions in Rust are private to the module they are
defined in and cannot be accessed from outside the module.
Developers can use the pub keyword to make functions public and
accessible from other modules.
pub fn subtract(a: i32, b: i32) -> i32 {
a - b
}
fn main() {
let result = subtract(7, 3);
println!("The difference is {}", result);
}
In this example, a function named subtract is declared as public using
the pub keyword, allowing it to be accessed from other modules in
the Rust project.
Understanding how to define, call, and utilize functions is essential
for mastering Rust's basic syntax and control flow. By leveraging
functions effectively, developers can write modular, reusable, and
maintainable code in Rust.
Control Flow: Conditions and Loops: Managing Program
Flow
Control flow mechanisms allow developers to dictate the flow of
execution in a program based on conditions and looping constructs.
This section explores conditions and loops in Rust, covering if
expressions, match expressions, and different types of loops.

If Expressions: Conditional Branching
If expressions in Rust allow developers to execute code based on the
evaluation of a condition. Unlike traditional if statements, if
expressions can return a value, making them versatile for assigning
variables or returning values from functions.
fn main() {
let number = 7;
let result = if number < 5 {
"less than 5"
} else if number > 10 {
"greater than 10"
} else {
"between 5 and 10"
};
println!("The number is {}", result);
}
In this example, an if expression is used to determine the relationship
between a variable number and specific thresholds, returning
different strings based on the evaluation of the condition.
Match Expressions: Pattern Matching for Complex Conditions
Match expressions in Rust provide powerful pattern matching
capabilities, allowing developers to handle complex conditions and
match against multiple patterns in a concise and expressive manner.
fn main() {
let number = 7;
match number {
1 => println!("One"),
2 | 3 | 5 | 7 | 11 => println!("Prime"),
_ => println!("Other"),
}
}
In this example, a match expression is used to categorize a number
based on its value. Patterns can include specific values, ranges, or
wildcard placeholders (_) for catch-all cases.
Loops: Iterating with Control

Rust provides several loop constructs for iterating over collections or
executing code repeatedly until a condition is met. The most common
loops are loop, while, and for, each offering different levels of
flexibility and control.
fn main() {
let mut count = 0;
loop {
println!("Count: {}", count);
count += 1;
if count >= 5 {
break;
}
}
}
In this example, a loop construct is used to print the value of a
counter variable count repeatedly until it reaches a specific threshold.
The loop is terminated using the break keyword when the condition is
met.
Understanding control flow mechanisms like conditions and loops is
essential for managing program flow and implementing complex
logic in Rust. By leveraging if and match expressions along with
different types of loops, developers can write efficient and expressive
code to handle various scenarios and conditions.
Error Handling: Strategies for Error Detection and
Resolution
Error handling is a critical aspect of writing robust and reliable
software. This section explores error handling in Rust, covering
strategies for detecting and resolving errors, including the Result
type, the ? operator, and custom error types.
Result Type: Handling Errors with Result
In Rust, the Result type is a generic enum used for error handling. It
has two variants: Ok, representing success with a value, and Err,
representing failure with an error. Functions that may fail typically
return a Result type to indicate success or failure.
use std::fs::File;

fn main() -> Result<(), std::io::Error> {
let file = File::open("example.txt")?;
println!("File opened successfully: {:?}", file);
Ok(())
}
In this example, the File::open function returns a Result<File,
std::io::Error>. The ? operator is used to propagate errors, returning
early from the function if an error occurs.
? Operator: Propagating Errors Concisely
The ? operator is a concise way to handle errors in Rust, allowing
functions to return early if an error occurs. It can only be used in
functions that return a Result type, automatically unwrapping the Ok
variant or returning the Err variant.
use std::fs::File;
use std::io::prelude::*;
fn write_to_file(data: &[u8]) -> std::io::Result<()> {
let mut file = File::create("output.txt")?;
file.write_all(data)?;
Ok(())
}
In this example, the write_to_file function writes data to a file named
output.txt. The ? operator is used to handle errors from both
File::create and write_all operations concisely.
Custom Error Types: Creating Meaningful Error Handling
Rust allows developers to define custom error types to represent
specific failure scenarios in their applications. Custom error types can
provide additional context and meaningful error messages, improving
the clarity and usability of error handling code.
use std::fs::File;
use std::io::{self, Read};
#[derive(Debug)]
enum CustomError {
FileOpenError(io::Error),
IOError(io::Error),
}

fn read_file_contents() -> Result<String, CustomError> {
let mut file = File::open("example.txt").map_err(CustomError::FileOpenError)?;
let mut contents = String::new();
file.read_to_string(&mut contents).map_err(CustomError::IOError)?;
Ok(contents)
}
In this example, a custom error type CustomError is defined to wrap
io::Error instances. Functions like File::open and read_to_string
return a Result type, which is mapped to the custom error type using
the map_err method.
Error handling in Rust is a powerful mechanism for dealing with
failures and ensuring the reliability of software systems. By
leveraging the Result type, the ? operator, and custom error types,
developers can handle errors effectively and provide meaningful
feedback to users in their applications.
Scope and Shadowing: Managing Variable Scopes in Rust
Scope and shadowing are important concepts in Rust for managing
variable lifetimes and visibility within different parts of a program.
This section explores how scope and shadowing work in Rust,
covering variable scope, variable shadowing, and nested scopes.
Variable Scope: Lifetime and Visibility
In Rust, the scope of a variable refers to the region of code where the
variable is valid and accessible. Variables can have either a global
scope, where they are accessible throughout the entire program, or a
local scope, where they are limited to a specific block of code.
fn main() {
// Variable with local scope
let x = 5;
// New block with its own scope
{
let y = 10;
println!("Inside inner scope: x + y = {}", x + y);
}
// Variable y is out of scope here
// println!("Outside inner scope: x + y = {}", x + y); // Error: `y` not found in this
scope
}

In this example, variables x and y have different scopes. The variable
x is accessible within the main function, while y is only accessible
within the inner block.
Variable Shadowing: Redefining Variables in Inner Scopes
Variable shadowing occurs when a variable with the same name is
declared within an inner scope, effectively hiding the outer variable
with the same name. This allows developers to reuse variable names
without causing conflicts or confusion.
fn main() {
let x = 5;
{
let x = 10; // Shadowing the outer variable x
println!("Inside inner scope: x = {}", x);
}
println!("Outside inner scope: x = {}", x); // The outer variable x is still accessible
}
In this example, the variable x is shadowed within the inner scope,
allowing a new variable with the same name to be defined without
affecting the outer variable.
Nested Scopes: Hierarchical Scope Structure
Rust supports nested scopes, allowing developers to create
hierarchical structures of code blocks with different levels of
visibility and access to variables. Nested scopes enable fine-grained
control over variable lifetimes and help manage resource allocation
and deallocation.
fn main() {
let x = 5;
{
let y = 10;
{
let z = 15;
println!("Inside nested scope: x + y + z = {}", x + y + z);
}
// Variable z is out of scope here

// println!("Outside inner scope: x + y + z = {}", x + y + z); // Error: `z` not found
in this scope
}
// Variable y and z are out of scope here
// println!("Outside outer scope: x + y + z = {}", x + y + z); // Error: `y` and `z` not
found in this scope
}
In this example, variables x, y, and z are declared within nested
scopes, with each inner scope having access to variables declared in
outer scopes.
Understanding scope and shadowing is crucial for managing variable
lifetimes and visibility in Rust programs. By leveraging these
concepts effectively, developers can write clear and maintainable
code while avoiding naming conflicts and managing resource
allocation efficiently..

Module 3:
Working with Collections: Handling
Data Structures
In this module, we delve into the world of collections in Rust, exploring
various data structures and how to work with them effectively. Collections
are essential for managing and manipulating data in any programming
language, and Rust provides a rich set of collection types to suit different
use cases.
Arrays and Vectors: Utilizing Array and Vector Data Structures
Arrays and vectors are fundamental data structures for storing collections of
elements in Rust. Arrays have a fixed size determined at compile time,
while vectors are dynamically resizable and can grow or shrink as needed.
Rust's arrays and vectors are both homogenous, meaning they can only
contain elements of the same type.
Rust's arrays are stack-allocated and have a fixed size determined by their
type signature. Vectors, on the other hand, are heap-allocated and can
dynamically resize themselves as elements are added or removed. This
flexibility makes vectors a versatile choice for managing collections of
varying sizes.
Slices: Efficiently Working with Subsets of Data
Slices provide a convenient and efficient way to work with subsets of data
stored in arrays, vectors, or other collections. Unlike arrays and vectors,
which own their data, slices are lightweight references to a contiguous
sequence of elements. This makes slices ideal for passing around portions
of data without incurring unnecessary copying.
Rust's slice syntax uses a range notation to specify the start and end indices
of the subset to be sliced. Slices can be created from arrays, vectors, or

other slices using the &[T] syntax, where T is the type of elements
contained in the slice. Additionally, slices support a range of operations,
including iteration, indexing, and borrowing.
Strings: Manipulating and Formatting Text Data
Strings are a common data type used for representing text data in Rust.
Rust's String type is a growable, UTF-8 encoded string, while string literals
(&str) are immutable references to string data stored in the program's
binary. Rust provides a rich set of methods for manipulating, formatting,
and working with strings efficiently.
Rust's string handling capabilities include methods for concatenation,
substring extraction, searching, replacing, and formatting. Rust's string
formatting syntax, based on the format! macro and the Display and Debug
traits, provides a flexible and expressive way to generate formatted string
output.
Tuples: Combining Heterogeneous Data in Rust
Tuples are another essential data structure in Rust, allowing developers to
combine multiple values of different types into a single, compound value.
Unlike arrays and vectors, which store homogenous collections of elements,
tuples can contain elements of different types, making them ideal for
representing ad-hoc data structures.
Rust's tuple syntax uses parentheses to group together the elements of the
tuple, separated by commas. Tuples can contain any number of elements,
and each element can have a different type. Rust's pattern matching
capabilities extend to tuples, enabling developers to destructure tuples and
extract their individual elements with ease.
This module provides a comprehensive overview of working with
collections in Rust, covering arrays, vectors, slices, strings, and tuples. By
understanding the strengths and capabilities of each data structure, you'll be
well-equipped to manipulate and manage data effectively in your Rust
programs.
Arrays and Vectors: Utilizing Array and Vector Data
Structures

Arrays and vectors are fundamental data structures in Rust for storing
collections of elements. This section explores arrays and vectors in
Rust, covering their syntax, initialization, accessing elements, and
common operations.
Arrays: Fixed-size Homogeneous Collections
Arrays in Rust are fixed-size collections of elements with a
homogeneous data type. Once defined, the size of an array cannot be
changed. Arrays are stack-allocated and have a fixed length known at
compile time.
fn main() {
// Declaration and initialization of an array
let numbers: [i32; 5] = [1, 2, 3, 4, 5];
// Accessing elements of the array
println!("First element: {}", numbers[0]);
println!("Third element: {}", numbers[2]);
}
In this example, an array named numbers is declared with a length of
5 and initialized with integer values. Individual elements of the array
can be accessed using square brackets ([]) and zero-based indexing.
Vectors: Dynamic-size Growable Collections
Vectors, also known as Vec in Rust, are dynamic-size collections of
elements with a homogeneous data type. Vectors can grow or shrink
in size dynamically at runtime. Vectors are heap-allocated and have a
flexible length.
fn main() {
// Declaration and initialization of a vector
let mut numbers: Vec<i32> = vec![1, 2, 3, 4, 5];
// Accessing elements of the vector
println!("First element: {}", numbers[0]);
println!("Third element: {}", numbers[2]);
// Adding elements to the vector
numbers.push(6);
numbers.push(7);
println!("Vector after adding elements: {:?}", numbers);
}

In this example, a vector named numbers is declared and initialized
with integer values using the vec! macro. Elements can be accessed
using square brackets ([]) and added to the vector using the push
method.
Common Operations: Iteration and Slicing
Both arrays and vectors support common operations such as iteration
and slicing. Iteration allows developers to perform operations on each
element of the collection, while slicing enables extracting a subset of
elements based on a range or condition.
fn main() {
let numbers: [i32; 5] = [1, 2, 3, 4, 5];
// Iterating over array elements
for num in numbers.iter() {
println!("Array element: {}", num);
}
let numbers_vec: Vec<i32> = vec![1, 2, 3, 4, 5];
// Slicing the vector
let slice = &numbers_vec[1..4]; // Extracts elements at indices 1, 2, and 3
println!("Sliced vector: {:?}", slice);
}
In this example, the iter method is used to iterate over elements of the
array, while slicing is performed on the vector to extract a subset of
elements.
Arrays and vectors are versatile data structures in Rust, suitable for
various use cases. By understanding their syntax and common
operations, developers can effectively utilize arrays and vectors to
store and manipulate collections of elements in their Rust programs.
Slices: Efficiently Working with Subsets of Data
Slices are a flexible and efficient way to work with subsets of data in
Rust without copying the original data. This section explores slices in
Rust, covering their syntax, creation, immutability, and common
operations.
Slice Syntax: Extracting Subsets of Data

A slice in Rust is a reference to a contiguous sequence of elements
within a collection, such as an array or a vector. Slices are denoted
using the range syntax start..end, where start is the starting index
(inclusive) and end is the ending index (exclusive).
fn main() {
let numbers = [1, 2, 3, 4, 5];
let slice = &numbers[1..4]; // Extracts elements at indices 1, 2, and 3
println!("Slice: {:?}", slice);
}
In this example, a slice named slice is created from the numbers
array, containing elements at indices 1, 2, and 3.
Immutable Slices: Read-only Access
Slices in Rust can be either immutable (read-only) or mutable,
depending on how they are declared. Immutable slices provide read-
only access to the underlying data and are useful when the data
should not be modified.
fn main() {
let numbers = [1, 2, 3, 4, 5];
let slice = &numbers[1..4]; // Immutable slice
println!("Slice: {:?}", slice);
// Attempting to modify the slice will result in a compilation error
// slice[0] = 10; // Error: cannot assign to `slice[..]`, as `slice` is an immutable
reference
}
In this example, the slice variable is an immutable reference to a
subset of elements from the numbers array, preventing modification
of the underlying data.
Common Operations: Iteration and Length
Slices support common operations such as iteration over elements
and obtaining the length of the slice. Iteration allows developers to
perform operations on each element of the slice, while the len method
returns the number of elements in the slice.
fn main() {
let numbers = [1, 2, 3, 4, 5];
let slice = &numbers[1..4]; // Immutable slice

// Iterating over slice elements
for num in slice.iter() {
println!("Element: {}", num);
}
// Obtaining the length of the slice
println!("Slice length: {}", slice.len());
}
In this example, the iter method is used to iterate over elements of the
slice, and the len method is called to obtain the length of the slice.
Slices are a powerful tool for efficiently working with subsets of data
in Rust. By understanding how to create, manipulate, and iterate over
slices, developers can write code that is both concise and efficient
when dealing with collections of elements.
Strings: Manipulating and Formatting Text Data
Strings are fundamental data types for representing and manipulating
text data in Rust. This section explores strings in Rust, covering
string creation, manipulation, formatting, and common operations.
String Creation: Initializing Text Data
In Rust, strings can be created using string literals or by converting
other data types into strings. String literals are enclosed in double
quotes (" "), and Rust's String type represents a growable, UTF-8
encoded string.
fn main() {
// Creating strings from string literals
let hello = "Hello, world!";
println!("String literal: {}", hello);
// Creating strings from other data types
let number = 42;
let number_string = number.to_string();
println!("Number converted to string: {}", number_string);
}
In this example, a string literal "Hello, world!" is assigned to the
variable hello, and an integer 42 is converted to a string using the
to_string method.
String Manipulation: Modifying Text Data

Strings in Rust can be manipulated using various methods provided
by the String type, such as concatenation, appending, and replacing
substrings. These methods allow developers to modify and transform
string data according to their requirements.
fn main() {
// Concatenating strings
let hello = "Hello, ";
let world = "world!";
let hello_world = hello.to_owned() + world;
println!("Concatenated string: {}", hello_world);
// Appending to a string
let mut message = "Rust".to_owned();
message.push_str(" is awesome!");
println!("Appended string: {}", message);
// Replacing substrings
let original = "Rust is awesome!";
let replaced = original.replace("awesome", "amazing");
println!("Replaced string: {}", replaced);
}
In this example, strings are concatenated using the + operator,
appended using the push_str method, and a substring is replaced
using the replace method.
String Formatting: Formatting Text Output
Rust provides powerful string formatting capabilities using the
format! macro and the println! and format! macros for formatted
printing. These macros allow developers to construct complex strings
with interpolated values and format specifiers.
fn main() {
let name = "Alice";
let age = 30;
let formatted = format!("Name: {}, Age: {}", name, age);
println!("Formatted string: {}", formatted);
}
In this example, the format! macro is used to create a formatted string
with placeholders {} for the name and age variables, which are then
printed using the println! macro.

Strings are essential for representing textual data in Rust, and
understanding how to create, manipulate, and format strings is crucial
for writing expressive and readable code. By leveraging Rust's string
manipulation and formatting capabilities, developers can handle text
data efficiently in their Rust programs.
Tuples: Combining Heterogeneous Data in Rust
Tuples are ordered collections of elements of varying types, making
them useful for grouping together values of different data types. This
section explores tuples in Rust, covering tuple creation, accessing
elements, destructuring, and common operations.
Tuple Creation: Grouping Heterogeneous Data
In Rust, tuples are created by enclosing comma-separated values
within parentheses (). Tuples can contain elements of different types,
allowing developers to group together heterogeneous data in a single
structure.
fn main() {
// Creating tuples with heterogeneous data types
let person = ("Alice", 30, true);
println!("Person tuple: {:?}", person);
}
In this example, a tuple named person is created containing a string,
an integer, and a boolean value.
Accessing Tuple Elements: Indexing and Destructuring
Tuple elements can be accessed using zero-based indexing or by
destructuring the tuple into individual variables. Indexing allows
direct access to specific elements, while destructuring enables
unpacking the tuple into its constituent parts.
fn main() {
let person = ("Alice", 30, true);
// Accessing tuple elements by indexing
println!("Name: {}", person.0);
println!("Age: {}", person.1);
println!("Is Active: {}", person.2);
// Destructuring the tuple

let (name, age, is_active) = person;
println!("Name: {}", name);
println!("Age: {}", age);
println!("Is Active: {}", is_active);
}
In this example, both indexing (person.0, person.1, person.2) and
destructuring (let (name, age, is_active) = person) are used to access
and print individual elements of the tuple.
Common Operations: Pattern Matching and Returning Tuples
Tuples can also be used in pattern matching and as return values from
functions. Pattern matching allows developers to match against
specific tuple patterns, while returning tuples enables functions to
return multiple values conveniently.
fn main() {
let person = ("Alice", 30, true);
// Pattern matching with tuples
match person {
(name, age, true) => println!("{} is {} years old and active", name, age),
(name, age, false) => println!("{} is {} years old and inactive", name, age),
}
// Function returning a tuple
fn get_person() -> (String, u32, bool) {
("Bob".to_string(), 25, false)
}
let (name, age, is_active) = get_person();
println!("Name: {}, Age: {}, Is Active: {}", name, age, is_active);
}
In this example, pattern matching is used to match against different
states of activity in the tuple, and a function get_person returns a
tuple containing information about a person.
Tuples provide a convenient way to group together heterogeneous
data in Rust. By understanding how to create, access, and manipulate
tuples, developers can effectively work with composite data
structures in their Rust programs.

Module 4:
Advanced Control Flow: Refining Flow
Control
In this module, we delve into advanced control flow mechanisms in Rust,
refining our ability to manage program flow with precision and efficiency.
Understanding these concepts is essential for writing expressive, logic-rich
code in Rust.
Pattern Matching: Advanced Data Extraction Techniques
Pattern matching is a powerful feature in Rust that enables advanced data
extraction and manipulation. It allows developers to match values against a
series of patterns and execute corresponding code blocks based on the
match. Rust's pattern matching syntax is expressive and concise, making it
well-suited for handling complex data structures.
Rust's match keyword is the primary mechanism for pattern matching,
allowing developers to match against enums, structs, tuples, and primitive
types. Patterns can include literals, variables, wildcards, and nested
patterns, providing fine-grained control over the matching process.
Additionally, Rust's exhaustive pattern matching ensures that all possible
cases are handled, reducing the risk of overlooked edge cases.
Advanced Looping Techniques: Iterating with Finesse
Loops are a fundamental construct in programming for repeating a block of
code until a certain condition is met. In Rust, loops can be augmented with
advanced techniques to enhance their expressiveness and efficiency.
Techniques such as loop labels, break statements with labels, and loop
guards provide fine-grained control over loop execution.
Rust's loop labels allow developers to break out of nested loops or specify
which loop to break or continue. This provides greater clarity and

readability, especially in complex loop structures. Additionally, loop guards
enable developers to conditionally break out of a loop based on a specified
condition, further enhancing the flexibility of Rust's looping constructs.
Early Returns: Optimizing Control Flow Patterns
Early returns, also known as "guard clauses" or "early exits," are a
programming technique used to improve code readability and
maintainability by reducing nesting and improving code flow. In Rust, early
returns can be achieved using the return keyword within functions to exit
early if a certain condition is met.
By strategically placing early returns in functions, developers can handle
exceptional cases or edge conditions upfront, reducing the cognitive load on
subsequent code blocks. This results in clearer, more focused code that is
easier to understand and maintain.
Exiting Programs: Graceful Program Termination Strategies
Graceful program termination is an essential aspect of writing robust
software that handles errors and exceptional conditions gracefully. In Rust,
developers can exit a program gracefully using the std::process::exit
function, which terminates the program with an optional exit code.
By providing informative error messages or logging information before
exiting, developers can help users diagnose and resolve issues more
effectively. Additionally, Rust's panic handling mechanisms provide a
fallback mechanism for handling unexpected errors and preventing abrupt
program termination.
This module equips you with advanced control flow techniques in Rust,
including pattern matching, advanced looping, early returns, and graceful
program termination strategies. By mastering these concepts, you'll be able
to write more expressive, efficient, and maintainable Rust code.
Pattern Matching: Advanced Data Extraction Techniques
Pattern matching in Rust is a powerful feature for deconstructing
complex data structures and extracting relevant information. This
section explores advanced techniques in pattern matching, covering
match arms, wildcards, guards, and destructuring.

Match Arms: Handling Multiple Patterns
Match arms allow developers to specify different patterns and
corresponding code blocks for handling each pattern. This enables
comprehensive and structured handling of various cases within a
single match expression.
fn main() {
let number = 5;
match number {
1 => println!("One"),
2 | 3 | 5 => println!("Two, Three, or Five"),
_ => println!("Other"),
}
}
In this example, the match expression matches against the value of
number and executes the corresponding code block based on the
matched pattern. The _ wildcard matches any value that does not
match the specified patterns.
Wildcards: Matching Any Value
Wildcards, denoted by the underscore _, match any value and are
useful for handling cases where specific patterns are not required.
Wildcards can be used as placeholders for patterns that are not
explicitly matched.
fn main() {
let age = 25;
match age {
0..=17 => println!("Child"),
18..=65 => println!("Adult"),
_ => println!("Senior"),
}
}
In this example, the match expression matches against the value of
age and categorizes individuals into different age groups. The range
patterns 0..=17 and 18..=65 match specific age ranges, while the _
wildcard matches any other value.
Guards: Additional Conditions

Guards are additional conditions applied to match arms, allowing
developers to further refine pattern matching based on specific
criteria. Guards are specified using the if keyword followed by a
condition.
fn main() {
let number = 12;
match number {
n if n % 2 == 0 => println!("Even"),
n if n % 2 != 0 => println!("Odd"),
_ => println!("Unknown"),
}
}
In this example, guards are used to distinguish between even and odd
numbers by checking the remainder when divided by 2. The match
arms with guards provide more precise handling of different cases.
Destructuring: Extracting Parts of Complex Structures
Destructuring allows developers to extract parts of complex data
structures, such as tuples, enums, or structs, directly within match
arms. This enables selective extraction and manipulation of specific
fields or components.
enum Shape {
Circle(f64),
Rectangle(f64, f64),
}
fn main() {
let shape = Shape::Circle(5.0);
match shape {
Shape::Circle(radius) => println!("Circle with radius: {}", radius),
Shape::Rectangle(width, height) => println!("Rectangle with dimensions: {} x
{}", width, height),
}
}
In this example, the match expression destructures the Shape enum
variant to extract the radius of a circle or the dimensions of a
rectangle. Destructuring simplifies access to individual components
of complex data structures.

Pattern matching is a versatile and expressive feature in Rust,
allowing developers to handle a wide range of scenarios with clarity
and precision. By mastering advanced techniques such as match
arms, wildcards, guards, and destructuring, developers can write
more concise and maintainable code in their Rust programs.
Advanced Looping Techniques: Iterating with Finesse
Looping constructs in Rust provide powerful mechanisms for
iterating over collections and performing repetitive tasks. This
section explores advanced looping techniques in Rust, covering
iterators, loop labels, early termination, and looping with conditions.
Iterators: Functional Iteration
Iterators in Rust provide a functional approach to iteration, allowing
developers to apply transformations and operations to elements of
collections. Iterators abstract away the details of looping and enable
concise and expressive code for processing data.
fn main() {
let numbers = vec![1, 2, 3, 4, 5];
// Using iterator methods to perform operations
let sum: i32 = numbers.iter().sum();
let doubled: Vec<i32> = numbers.iter().map(|x| x * 2).collect();
println!("Sum: {}", sum);
println!("Doubled: {:?}", doubled);
}
In this example, iterators are used to calculate the sum of elements
and double each element in a vector. Iterator methods such as sum
and map enable functional-style programming for data processing.
Loop Labels: Breaking out of Nested Loops
Loop labels, also known as loop identifiers, provide a way to break
out of nested loops by specifying a label for the outer loop. This
allows developers to control the flow of execution and exit from
multiple nested loops simultaneously.
fn main() {
'outer: for i in 1..=3 {

'inner: for j in 1..=3 {
if i * j == 6 {
println!("Breaking out of both loops");
break 'outer;
}
}
}
}
In this example, the 'outer label is applied to the outer loop, and the
'inner label is applied to the inner loop. When the condition i * j == 6
is met, the break 'outer statement breaks out of both loops
simultaneously.
Early Termination: Breaking and Continuing Loops
Rust provides the break and continue keywords for early termination
and skipping iterations within loops, respectively. These keywords
enable fine-grained control over loop execution and allow developers
to handle exceptional cases efficiently.
fn main() {
let numbers = vec![1, 2, 3, 4, 5];
// Breaking out of a loop early
for &num in &numbers {
if num == 3 {
break;
}
println!("{}", num);
}
// Skipping iterations in a loop
for &num in &numbers {
if num % 2 == 0 {
continue;
}
println!("{}", num);
}
}
In this example, the first loop breaks early when encountering the
value 3, while the second loop skips iterations for even numbers
using the continue keyword.
Advanced looping techniques in Rust provide developers with
powerful tools for efficient and expressive iteration over collections

and control flow within loops. By leveraging iterators, loop labels,
early termination, and looping with conditions, developers can write
concise and effective code for handling various scenarios in their
Rust programs.
Early Returns: Optimizing Control Flow Patterns
Early returns in Rust allow developers to optimize control flow
patterns by exiting functions prematurely under certain conditions.
This section explores techniques for early returns in Rust, covering
the return keyword, Result type, Option type, and conditional returns.
Early Returns with the return Keyword
The return keyword in Rust is used to exit a function early and return
a value from the function. Early returns are commonly used to handle
exceptional cases or validate inputs at the beginning of a function,
improving code readability and maintainability.
fn divide(x: f64, y: f64) -> Option<f64> {
if y == 0.0 {
return None; // Return early if denominator is zero
}
Some(x / y) // Return the result of division
}
fn main() {
let result = divide(10.0, 5.0);
println!("Result: {:?}", result);
}
In this example, the divide function returns None early if the
denominator y is zero, avoiding division by zero errors. Otherwise, it
returns Some(x / y) with the result of the division.
Early Returns with the Result Type
The Result type in Rust is used to represent the success or failure of
an operation. Functions that may fail typically return a Result type,
allowing early returns with an error value if the operation fails.
fn divide(x: f64, y: f64) -> Result<f64, &'static str> {
if y == 0.0 {
return Err("Division by zero"); // Return early with an error
}

Ok(x / y) // Return the result of division
}
fn main() {
let result = divide(10.0, 0.0);
match result {
Ok(value) => println!("Result: {}", value),
Err(error) => println!("Error: {}", error),
}
}
In this example, the divide function returns Err("Division by zero")
early if the denominator y is zero, indicating a division by zero error.
Otherwise, it returns Ok(x / y) with the result of the division.
Conditional Returns: Using if Expressions
Conditional returns in Rust enable developers to return different
values or types based on specific conditions within a function. This
allows for concise and expressive handling of different scenarios and
edge cases.
fn calculate_price(quantity: i32, price_per_unit: f64) -> Option<f64> {
if quantity <= 0 {
return None; // Return early if quantity is zero or negative
}
Some(quantity as f64 * price_per_unit) // Return the calculated price
}
fn main() {
let price = calculate_price(5, 10.0);
println!("Price: {:?}", price);
}
In this example, the calculate_price function returns None early if the
quantity is zero or negative, avoiding calculation errors. Otherwise, it
returns Some(quantity as f64 * price_per_unit) with the calculated
price.
Early returns in Rust enable developers to handle exceptional cases
efficiently and improve the readability and maintainability of their
code. By leveraging the return keyword, Result type, Option type,
and conditional returns, developers can write robust and concise
functions that gracefully handle various scenarios.

Exiting Programs: Graceful Program Termination
Strategies
Exiting programs gracefully in Rust involves ensuring proper
resource cleanup and providing meaningful exit codes or error
messages. This section explores strategies for terminating Rust
programs effectively, including std::process::exit, error handling,
panic handling, and cleanup routines.
Using std::process::exit
The std::process::exit function is a direct way to terminate a Rust
program with an exit code. It immediately terminates the program,
bypassing any cleanup routines or destructors.
use std::process;
fn main() {
if some_condition() {
println!("Exiting program due to condition");
process::exit(1); // Exit with a non-zero exit code
}
// Rest of the program continues if condition is not met
}
fn some_condition() -> bool {
// Some condition check
true
}
In this example, if the some_condition function returns true, the
program exits with an exit code of 1. Otherwise, the program
continues execution as usual.
Error Handling for Graceful Termination
Error handling in Rust provides a mechanism for gracefully handling
errors and exiting programs in case of failures. By returning Result or
Option types from functions and using match or unwrap to handle
errors, developers can ensure proper cleanup and error reporting.
fn main() {
if let Err(err) = do_something() {
eprintln!("Error: {}", err);
process::exit(1); // Exit with a non-zero exit code

Random documents with unrelated
content Scribd suggests to you:

Samassa kaatoi hänet hiljaa suhahtava nuoli.
Asemiehet tulivat pian takaisin monen sadan keihäänkantajan
saattamina, mutta kaikki pysähtyivät siihen pelästyneinä ja
kalpenivat. Etumaiset väistyivät taaksepäin ja astuivat toisten
rautakengille. He näkivät kaikki selvästi ja varmasti valoisassa
metsässä, mutta he eivät huomanneet ainuttakaan ihmistä, ja
lakkaamatta kaatoivat hiljaa suhahtavat nuolet toisen heistä toisensa
jälkeen.
Yht'äkkiä syöksähti koko hyppivien jättiläispäiden ja irvistelevien
hevosenkallojen kummitusjoukko piilostaan, ja perässä seurasi tiheä
rivi piikkinuijia ja keihäitä.
Mutta silloin rynkäsi myös toiselta puolen näkyviin kuin susilauma
harmaja rivi yltä päältä rautaan puettuja miehiä. He heittäytyivät
pitkin pituuttaan maahan. He loikkasivat tukevin hypyin eteenpäin,
raskaista varustuksistaan huolimatta, ja aina tekivät heidän
miekkansa totta. Ei kukaan voinut heitä vastustaa. Kirveet lyötiin
käsistä, nuolet ja keihäät taittuivat heidän rautapaitojaan vasten kuin
korret. Mutta kun he tapasivat vanhuksen tai puolikasvuisen,
pidättivät he aseensa iskemästä ja löivät häntä olalle, sanoen: "Mene
rauhassa! Jeesus Kristus elää."
Ja heti kajahti heidän takaansa Tivedin honkien alta satojen
suiden huuto: "Kyrieleis, Kyrieleis!" ["Kyrieleis", lyhennys sanoista
"Kyrie eleison" (Herra armahda!), oli riemuhuuto, jonka ristiretkeilijät
ja pyhiinvaeltajat usein kohottivat.]
He tempasivat kummituksilta näiden oudot varusteet. Mutta kun
he tulivat uhkaavain naisten keskeen, käänsivät he miekkansa
ponnen ylöspäin ja kumarsivat päänsä. Etumaisin heistä oli samalla

myös kookkain ja taitavin. Hänellä oli kulunut, sileä kypärä,
kummankin silmän kohdalla pieni musta rako. Hänen miekkansa isku
halkaisi Tin aina juuriin asti, ja lahonneet luut ja kaarnanpalaset
lentelivät ylt'ympäriinsä. Hänet tunsi helposti herttuaksi. Hänen
takanaan kulki hänen hevosensa kuin uskollinen koira ikään, ilman
että hänen tarvitsi pitää sitä suitsista. Vähitellen oli tullut päivä
jälleen, ja metsänväki kirmaisi pakoon puu puulta. He tunsivat,
etteivät loitsut eivätkä taikatemput auttaneet enää mitään, että
pakanuus oli kukistettu, että hurjat metsänjumalat pakenivat heidän
laillaan ja ryömivät kivien ja rauniokasojen alle kuin mäyrät ja ketut,
sinne kuolemaan tai valittaen ulvomaan pitkinä talvi-öinä.
"Voi meitä, tuhon omia", huusivat metsänkävijät. "Nyt ottavat
ritarit maan haltuunsa. Kas, kas, kyyhkysiä lentelee heidän
kypäriensä yllä!"
Herttuan joukko kasvoi yhä, ja ritarit lauloivat Maunun lipun
ympärillä:
    Ritarit näin rukoilevat Luojaa:
    Antaos paistaa armosi tähden
    Kypärään, mi otsaamme suojaa
    Orpoin, kurjain, osatonten tähden!
Heti kun he olivat lopettaneet, jatkoivat laulua ne, jotka seisoivat
alhaalla suon reunassa:
    Ritarit näin rukoilevat Luojaa:
    Keskellä maailman kyynelteitä
    Sodista verisistä suojaa,
    Rauhaan, oi rauhaan johdata meitä!

Maunu riisui kypäränsä, ja hänen voimakkaat, ruskeat
soturipiirteensä paljastuivat. "Moran kiville kuninkaaksi
julistettavaksi!" huusi koko ritarijoukko, raikuvasti osoittaen iloaan ja
kalistaen kilpiään, sillä nyt oli maa pelastettu rappiosta ja
voimattomuudesta.
Valdemar kuoli sitten vankilaansa Nyköpingin linnaan. Mutta
Maunua ja hänen loistavaa ritarihoviaan mainittiin kunnioittaen
kaikissa Pohjolan maissa, ja hän pani uusia perustuksia valtakunnan
menestymiselle. Häntä kutsuttiin myöhemmin Maunu Latolukoksi, ja
taru on tahtonut selittää sen nimen niin, että hän jokaisen oikeutta
suojelevilla laeillaan pani ikäänkuin lukon talonpojan ladon oveen.

XVIII.
TORKKELI NUUTINPOIKA.
Kun Maunu Latolukko taudin murtamana istui linnassaan Vising-
saarella
ja tunsi loppunsa lähestyvän, kutsui hän marskinsa Torkkeli
Nuutinpojan luokseen. "Kolme poikaani ovat vielä pieniä", sanoi hän.
"Hallitse sinä uskollisesti valtakuntaa!"
Poikien nimet olivat Birger, Eerikki ja Valdemar. Marskista tuli viisas
holhooja, ja kansa sanoi: "Nyt ei puutu iloa, tanssia eikä turnajaisia
isoisten linnoista, eikä viljaa, silavaa eikä silliä maanmiesten taloista.
Eivätpä tule asiat pian olemaan taas niin hyvin kuin nyt Torkkeli
Nuutinpojan päivinä."
Kun kuningas Birger oli kahdeksantoista, vietti hän häitään
Tanskan kuninkaan Eerikki Menvedin sisaren kanssa; tämä kuningas
oli taas aikaisemmin nainut hänen sisarensa.
Häät vietettiin Tukholmassa, ja marski avasi rennosti valtakunnan
pussia. Tarkkaavain kuulijain ympäröiminä seisoi ilvehtijöitä ja
kierteleviä soittoniekkoja pöydillä ja tynnyreillä kirkumassa

tuoreimpia uutisia, koska siihen aikaan ei vielä ollut sanomalehtiä.
Jokaista tunnettua ritaria, joka ratsasti ohi, tervehdittiin iloisin
huudoin. Taloista, joihin ritarit majoitettiin, pistettiin heidän
peitsiviirinsä liehumaan akkunasta, niin että vaakunakoristeisia
lippuja näkyi kaikkialla, minne katsoikin. Korkeimmalle kohosi riemu,
kun kuninkaan molemmat veljet ratsastivat kaupunkiin. Valdemarista
ei kukaan välittänyt, mutta Eerikkiä tahtoivat kaikki tervehtiä. Hän
säteili nuoruutta ja korskeutta, ja kun hän kohotti kätensä, näytti
hän mielivän poimia kultasäkkejä ja kuninkaankruunuja taivaan
pilvistä. "Toimita tuo roskajoukko pois tieltä!" sanoi hän
aseenkantajalleen. "En halua hangata jalkaani rääsyihin." Mutta
väkijoukon ainoana vastauksena oli uusi riemun kohina.
Vihdoin puhalsivat torvet turnaukseen. Rouvat ja neidot, jotka
istuivat kilpatantereen laidoilla, hopeaseppeleet ja pehmeät huivit
päässä, kohottautuivat kiihtyneinä penkeiltään. Peitsi kainalossa
ryntäsivät ritarit toisiansa vastaan hevostensa selässä, ja taampana
varustelivat asemiehet patjoja haavoittuneille. Alhaisemmallekin
kansalle juoksi sinä iltana simaa, olutta ja kirsikkaviinaa. Yksi huitoi
veitsellä, toinen pullollaan, ja kenellä ei ollut mitään asetta, raastoi
riitaveljeänsä tukasta. Suurin oli tungos sen hirsisalin edustalla, joka
oli erityisesti rakennettu ritarien kemuja varten. Siellä tarjosivat
hovipojat ruoka-astioita polvillaan, ja siellä ei käynyt niistäminen
nenää sormiin eikä kaiveleminen korvaa veitsenpäällä. Tuskinpa oli
luvallista puhdistaa hampaitansa veitsenkärjellä. Jos joku joi toisen
maljan, tapahtui se kohteliaasti, silmät maahan luotuina, eikä luita
laskettu takaisin lautaselle, vaan heitettiin pöydän alle, missä koirat
niistä tappelivat. Siellä olikin toisenmoisempi elämä kuin
poroporvarien pidoissa.

Herttua Eerikki piti seuraavana päivänä lyötämän ritariksi.
Hämärän tullessa otti hän ritarikylvyn. Valkeaan mekkoon puettuna
valvoi hän sitten koko yön toisten ritarien kanssa harmaiden
munkkien kirkossa, jota nyt sanotaan Riddarholman kirkoksi. Siellä
polvistui hän Maunu Latolukon hautapaadelle pää-alttarin eteen ja
rukoili: "Isä, opeta minua kaikessa tulemaan sinun kaltaiseksesi!"
Mutta syvällä hänen sydämessään, niin syvällä, että hän itse sen
tuskin kuuli, kuiskasi synkkä ääni: "Ja sinun laillasi, jos niin tarvitaan,
tempaamaan kruunu heikolta, houkkamaiselta veljeltä."
Kauvaksi kuului hälinä seuraavana aamuna, kun hän
kilpatantereella astui kuningas Birgerin eteen. Birger istui kalpeana
kunniakatoksen suojassa morsiamensa, kuningatar Märtan rinnalla.
Morsiamella oli pieni suu, mutta se ei voinut koskaan hymyillä, ja
punaiset hiuskiehkurat parveilivat kultarivan ympärillä. Kirkkaalla
äänellä vannoi Eerikki ritarivalan: hän lupasi sotia pyhän uskon
vahvistamiseksi, vastustaa vääryyttä, suojella turvattomia ja orpoja,
inhota vilppiä ja taistella totuuden ja oikeuden puolesta. Birger löi
häntä silloin miekanlappeella hartioihin ja huudahti: "Havahtuos
pahuuden unesta, kasvaos rauhan sotijaksi ja ollos aina Jumalalle
kuuliainen!" Sitten antoi hän veljelleen rauhansuudelman. Miekka
ripustettiin hänen kupeelleen, kultaiset kannukset kiinnitettiin hänen
kantapäihinsä ja sulkatöyhtöinen kypärä pantiin hänen päähänsä. Ja
niin oli Eerikki ritari.
Torkkeli iloitsi, kuten olisi iloinnut isä omista lapsistaan. Hänen
kärpännahalla reunustetusta viitastaan näkyi, että hän rakasti
komeutta ja että hän oli suurisukuinen ja rikas, ja hänellä olikin sekä
taloja että kaivoksia. Kuin uusi Birger Jaarli johti hän kaikkea, mutta
hän oli hyvänsävyisempi ja nöyrempi, ja hän oli tyytyväinen
nähdessään muut tyytyväisinä. Hänen leveiden, leppeiden

piirteidensä ympärillä alkoivat jo hiuskiharat harmaantua, mutta vielä
kykeni hän heittämään miekkansa ilmaan ja sieppaamaan sen
kahvasta jälleen käteensä. Se miekka oli seurannut häntä monille
sotaisille seikkailuille Karjalan erämaihin Itämeren toiselle puolen. Ja
kun kisat ja juhlat nyt olivat lopussa, alkoi hän jälleen ajatella
Ruotsin vallan laajentamista.
Komea sotalaivasto mukanaan purjehti hän Nevaa ylös ohi
rämeisten rantain, missä nyt Pietarin kullatut kupoolit kimaltelevat,
mutta missä silloin syvää hiljaisuutta häiritsi vain suolintujen kirkuna
ja räkätys. Sinne rakensi hän linnoituksen.
Venäläiset kokosivat silloin sotajoukon, jossa oli väkeä
silmänkantamattomiin. He panivat suunnattomia palavia rovioita
solumaan virtaa alas ruotsalaisten laivoja kohti, mutta marski vedätti
rautavitjoja rannasta rantaan ja esti ne siten kulkemasta. Komeita
kypärejä ja varustuksia välkkyi metsästä, minne venäläiset
leiriytyivät. Muuan nuori, peloton sankari, jonka nimi oli Matti
Kättilmundinpoika, ratsasti silloin nostosillan yli ja toivotti
sotatovereilleen ylhäällä vallilla hyvää voimista. Sillä nyt tiesi vain
Jumala taivaassa, palaisiko hän koskaan enään elävänä heidän
luokseen. Sitten käski hän tulkin huutamaan venäläisille, että hän oli
valmis ottelemaan urhokkaimman kanssa heidän joukostaan.
Voitetun tulisi seurata voittajaansa vankina hevosineen ja
varustuksineen.
Venäläiset pitivät silloin neuvottelua keskenään, mutta yksikään ei
rohjennut käydä kiistaan. Koko päivän istui hän siinä hevosensa
selässä vihollista vastapäätä ja odotti. Vasta kun päivänpyörä alkoi
painua metsän taa, käänsi hän hevosensa ja ratsasti takaisin linnaan,
missä häntä tervehdittiin ystävällisin kädenpuristuksin. Mutta

aamulla havaitsivat ruotsalaiset venäläisten menettäneen halunsa
taistella moisia uroita vastaan ja livistäneen tiehensä.
Marski purjehti silloin kotiin Ruotsiin, missä kaikki osoittivat hänelle
mitä suurinta kunnioitusta.
Hän alkoi nyt kaivata rauhaa, ja kun hän Birgerin kruunajaisissa oli
naittanut nuorimman tyttärensä Valdemarille, pyysi hän vapautusta
valtakunnan hoidon raskaista tehtävistä. Veljet vastasivat, etteivät he
voisi löytää siihen tehtävään sopivampaa miestä, ja he saivat hänet
rupeamaan vieläkin Birgerin avustajaksi. Pian joutuivat he kuitenkin
riitaan mitättömistä pikku-asioista ja alkoivat epäillä toisiaan, mutta
herttuat saivat kokea, että marski pysyi uskollisesti Birgerin puolella.
"Niin kauvan kuin hän elää", ajattelivat he, "ei meillä ole vähintäkään
sananvaltaa maassa". Sentähden uskottelivatkin he Birgerille, että
tuo kunnianarvoisa marski oli ainoana syynä epäsopuun.
Päivänä muuanna istui Torkkeli Kungslenassa, jonne hän oli
vetäytynyt, toipuakseen erään pitkän matkan rasituksista. Silloin
raotti palvelija ovea ja kuiskasi: "Minä näen kuningas Birgerin
tulevan tänne veljineen, paljon aseistettuja miehiä mukanaan.
Joutuin rekeen, marski, jos henkesi on sinulle rakas!" Torkkeli
katsahti häneen hämmästyneenä ja vastasi: "Toivoisin palvelleeni
Jumalaa yhtä hyvin kuin kuningastani. Hän on minun ystäväni, ja
minä olen hänen ystävänsä."
Joukkue törmäsikin äkkiä sisään paljastetuin asein, ja herttuat
huusivat: "Niin kauvan kuin tuo mies elää, ei tule koskaan rauhaa
meidän veljesten välille." Birger seisoi heidän vieressään tuhkan
harmaana ja tahdottomana, lausumatta sanaakaan. Silloin nousi
Torkkeli jaloilleen ja huudahti: "Häpeää saat sinä kantaa tästä,
kuningas, koko elinikäsi!"

Sitten raastettiin hänet ulos ja nostettiin hevosen selkään, ja
hänen jalkansa sidottiin hevosen mahan alle. Niin kuljetettiin häntä
sitten lumessa ja pakkasessa läpi Tivedenin lyhyinä talvipäivinä,
jolloin aurinko paistoi vain hetkisen, ja pitkinä talvi-öinä. Monet
hevoset oli jo ratsastettu väsyksiin, ennenkuin he vihdoin saivat ukon
Tukholmaan ja torniin suljetuksi.
Valdemar hylkäsi hänen tyttärensä. Kun marski käveli kosteassa
kopissaan ja ajatteli, kuinka uskollisesti hän oli palvellut herraansa,
kuuli hän soittoa ja tanssia saleista, missä veljekset viettivät iloisia
päiviä äkillisen sovun ja tyytyväisyyden valtaamina. Eräänä päivänä
tuli muuan ritari alas hänen luokseen ja sanoi: "Tee testamenttisi ja
ripitä itsesi, sillä kuningas tahtoo sinun kuolemaasi. Suo anteeksi,
että minun on täytynyt tuoda sinulle tällainen sanoma. Siitä on oleva
mieleni raskas viimeiseen hetkeeni asti."
Sitten vietiin marski sille paikalle, missä Södermalmin tori nykyään
sijaitsee. Siellä oli silloin syöttömaita, ja tupa, jopa parikin törrötti
tien poskessa. Hän sai polvistua odottamaan miekaniskua, ja heti
kun hänen kaulansa oli katkaistu, kaivettiin hänen ruumiinsa
maahan. Haudalle kohottivat hänen heimolaisensa ja palvelijansa
alttarin ja ristin, ja ne, jotka muistivat hänen onnensa vuodet,
rukoilivat siellä hänen sielunsa puolesta. Kun kevät taas tuli,
muutettiin hänen ruumisarkkunsa harmaiden munkkien kirkkoon ja
haudattiin muutamien askeleiden päähän Maunu Latolukon
muistopaadesta. "Rauhaton on kait unesi nyt, Maunu Latolukko",
ajattelivat ne, jotka arkkua kantoivat. "Miten on nyt käyvä poikiesi?"

XIX.
NYKÖPINGIN PIDOT.
VAIHDOKKAAN LAHJA.
Metsissä paistoi pihlajanmarjoja punaisenaan, ja se tiesi ankaraa
talvea. Jottei paleltuisi pakkasen tullen, laahasi muuan talonpoika
tupaansa kokonaisen kuusenrungon ja laski sen lieden reunalle. Hirsi
oli niin pitkä, että se ulottui kynnykselle asti. Sitä myöten kun latva
paloi, sysäsi hän puuta ylemmäksi hiilikasaan. Sillä tavalla ei häneltä
koskaan tuli loppunut.
Väliin yöllä, kun pakkanen hurjimmin paukkui, kuuli hän tonttujen
ja menninkäisten hiljaa hiipivän huoneeseen ja jäävän siihen
ovensuuhun hytistelemään ja vaikertelemaan. Mutta heti kun ne
olivat saaneet kätensä ja jalkansa hiukan sulamaan, kiipesivät ne
iloisina ja vallattomina kuusenrungolle. Siihen sopi niitä istumaan
kahareisin seitsemän, kahdeksan kappaletta. Ne olivat aika rumia
köntyksiä, ja niiden kasvot olivat kurttuiset, ja kovin ijäkkäiltä ne
näyttivät. Kun niiden vaatteet tarttuivat pihkaan, nauroivat ne niin
tuhottomasti, että menettivät tasapainonsa ja tipahtelivat
permannolle.

Talvi pimeni yhä, ja niin tuli Lucian yö. Se yö oli niin pitkä, että
kukkokin nukahti yli aikansa ja unohti kiekua. Ja silloin torkahtivat
kaikki nuo kahdeksan tonttua lynkämäisilleen puunrungolle. Kun
aurinko pilkisti tupaan ja herätti talonpojan, hypähti hän vuoteensa
oljilta ja sai lähimmän peikon käsiinsä. "Nyt sinut paha perii, sinä
häijy rumilas", sanoi hän, ravisteli menninkäistä oikein olkansa takaa
ja piteli sitä auringon valojuovassa. "Kyllä minä tiedän, millä tavalla
moisesta otuksesta loppu tehdään."
Kun päivänsäde oli hetkisen valaissut peikkoa, halkesi se
pamahtaen ja lysähti kasaan ja näytti nyt aivan joltakin
ruskeanahkaiselta pussilta. Talonpoika ripusti nahan seinälleen ja
aikoi siitä oivaa metsästyslaukkua.
Siihen asti olivat peikot olleet hyväntahtoisia ja säyseitä. Mutta
seuraavana yönä varastivat ne talonpojan pienen vakahaisen tyttären
Cicillan ja panivat sijaan oman menninkäislapsensa. Talonpoika oli
leskimies. "Kuka sinä olet?" kysyi hän, kun hän herätessään näki
ruskean veitikan istuvan oljilla ja pöyhivän mustaa, takkuista
tukkaansa. "Nimeni on Trulla-Ho", vastasi vaihdokas ja keikkui
maitokulholle lyhyillä, väärillä säärillään. Käsivarret olivat niin pitkät,
että sormet laahasivat maata.
Se söi ja joi kaikki, mitä suinkin sai, mutta vain maha ja pää
kasvoivat. Talonpoika ei voinut milloinkaan unohtaa kaunista,
sinisilmäistä Cicillaansa, vaan suri itsensä kuoliaaksi. Trulla-Ho jäi
silloin yksikseen tupaan.
Tuvalle johtava polku kasvoi pian umpeen. Vain noita-akat
uskalsivat sitä polkua kulkea, sillä heidän majojansa oli siellä ja täällä
metsässä. Ne olivat kummallisia vanhoja eräkkäitä, jotka välttivät

ihmisten seuraa, mutta viihtyivät Trulla-Hon parissa, ja Trulla-Ho
opetti heille monta salaista taitoa omista peikkotiedoistaan.
Kappaleen matkaa siitä törrötti vielä se kiviröykkiö, johon Ura-
Kaipa haudattiin tuhansia vuosia sitten. Sen ympärille kokoontuivat
noita-akat eräänä kiristuorstainiltana. Voidesarvistaan sivelivät he
voita ja ihraa ylimmän kiven pieniin uhrikuoppiin eli hiidenmyllyihin
ja polttivat tikkusista ja rievuista valmistettuja nukkeja. Liekit
loimusivat, ja tuulenkaataman puun juurien takaa helotti täysikuu.
Muuan noita-akka, joka tunsi olevansa loihdittu kalaksi, aukoi ja sulki
lakkaamatta suutaan, puhumatta sanaakaan. Vihdoin alkoi hän
puhaltaa jotakin säveltä hirsipuun alta löytämällään varkaan
sääriluulla. Silloin pyörivät toiset laulaen ympäri kiveä kuin lauma
harmaita susia. Ja heidän juohotuksensa oli kuin hiljaista haukuntaa:
    "Kuolonhirsi vihannoi,
    Kallo vainaan teutaroi,
    Hurme huppeloi.
          Hi iden ukon
          Uhri suuri:
          Jalka kuk on,
          Lepän juuri.
Musulavi, avi, extraborum, sumulus sumin peccatorum, ai
ain et arri."
Kalpea mies kullankimaltelevassa puvussa läheni pensaiden
välitse. Hänen silmäluomensa olivat punaiset kuin itkusta tai
unettomuudesta, mutta hän hykerteli mielipuolen lailla käsiään ja
katseli huvitettuna ja tyytyväisenä ympärilleen. Hänen asemiehensä
kantoivat joutsia ja haukkoja, sillä hän oli metsältä palaamassa. Ne

koettivat saada häntä kääntymään pois, mutta hän piti oman
päänsä. "Minä olen kuningas Birger", sanoi hän noita-akoille
onnellinen hymy huulilla. "Märta, kuningattareni, saisitpa vain
kerrankin nähdä moisen ilveilyn, niin varmasti hymyilisit!"
"Onko sinun kuningattaresi sitten niin vaikeata vetää suutansa
nauruun?" kysyi Trulla-Ho, ja karkelo taukosi.
Birger painui alakuloiseksi ja katse harhaili. "Hänen
huulenseutunsa tästä näin ovat jäykät", kuiskasi hän ja nosti sormet
kasvoilleen. "Tiedätkö siihen mitään keinoa, noita-akka?"
"Luulenpa, että hän saa nauraa vielä kymmenen kertaa
hullummalle noitajuhlalle kuin tämä, jos tahdot." Ja hän ojensi
Birgerille hiukan nöhtää, jota oli kihnautunut kahden
yhteenkasvaneen puun välistä. "Epäsopua ja veljesvihaa ne hahtuvat
sisältävät", mumisi hän niin hiljaa ja sekavasti, ettei kuningas kuullut
mitään. Sitten lisäsi hän hiukan kovempaa: "Heitä tätä muutamia
hyppysellisiä mesijuomaan, kun kemuilet veljiesi kanssa, kuningas
Birger!"
Kuningas Birger pisti lahjan viittansa kätköihin ja jatkoi sitten,
onnellinen hymy huulilla, kolkkoa vaellustaan läpi kuunpaisteisen
metsän.
CICILLA METSÄSSÄ.
Mikonpäivän aikoihin, jolloin lappalaiseukkojen oli tapana seisoa
tuntureillaan houkuttelemassa luokseen metsän lintua, oli melskettä
ja melua Håtunan kuninkaankartanossa.

Syyskuiset lehdet alkoivat varista ja peittää maata keltaisella
verhollaan. Vain lepät kuvastivat vielä tummaa vehreyttänsä Mälarin
lahteen. Hunhammarista päin souti joukko veneitä, ja ensimäisessä
niistä olivat herttuat Eerikki ja Valdemar. Ei ollut vielä vuottakaan
kulunut siitä, kun he olivat puhuttaneet veljensä vangitsemaan jalon
kasvatusisänsä, Torkkeli Nuutinpojan.
Kuningas Birger, joka vietti juhlaa Håtunassa ja oli juuri käymässä
pöytään, otti heidät hyvin vastaan ja toimitti heidän miehensä
vierastaloon. Siellä varustautuivat kutsumattomat vieraat salaa
aseilla ja illalla ryntäsivät he talosta ja vangitsivat ja raahasivat
mukaansa sekä kuningattaren että kuninkaan. Kuningatarta
juoksuttivat he vielä pitkät matkat hevosten välissä.
Arvid Smålantilainen, uskollinen hovimies, sai kahakan
temmellyksessä siepatuksi syliinsä Birgerin kuusivuotiaan pojan
Maunun ja paetuksi. Hän nosti pojan väkeville hartioilleen ja viihdytti
häntä parhaansa mukaan. "Pikku herttua", sanoi hän, "ei tuo ole
metsälintu, joka illalla käy levottomaksi ja läiskii siipiään. Minä
kuulen väsyneiden hevosten huohottavan aivan takanamme, mutta
minä tiedän polkuja, joille ei kukaan osaa meitä seurata. Pitkä on
matka läpi erämaiden ja yli järvien enosi, Tanskan Eerikki Menvedin,
luo, mutta minä kannan sinut sittenkin sinne, niin että pääset
turvaan. Hän sinusta kasvattaa ritarin."
Päivän koittaessa heittäytyi Arvid väsyneenä hetkiseksi sammaliin
ja nukahti. Silloin näki Maunu hyvin kummallisen näyn. Peikoilla oli
siinä aivan lähellä asuinkumpunsa, ja siitä ilmestyi pieni
tytöntypykkä, joka oli suloisin olento, mitä voi ajatella. Vaikkei hän
näyttänyt juuri Maunua vanhemmalta, täytyi hänen kumartua, jottei
satuttaisi päätänsä käytävän multakattoon. Hän levitteli kääpiöiden

kankaita nurmelle valkenemaan, ja ne kimaltelivat ja välkkyivät ja
olivat niin ohuita, että puolukat paistoivat niiden läpi.
Siinä oli Cicilla, talonpojan tytär, jonka peikot olivat varastaneet.
Entistä kotiansa ei hän enää lainkaan muistanut, mutta maahiset
olivat kastaneet hänet sannalla omaan tapaansa ja antaneet hänelle
pienen hopeamaljan kumminlahjaksi. Ne pelkäsivät kovin ukkosta ja
uskalsivat ulos vain pilvisäällä, jolloin aurinko oli peitossa, mutta
kummussaan kisailivat ne iloisesti ja olivat tyytyväisiä.
Tyttönen piti Maunua kääpiönä, joka oli tullut vieraisille ja ojensi
hänelle kätensä. "Käy sisään", pyysi hän. Maunu ryömi silloin hänen
kanssaan kumpuun, ja maahiset panivat pöydälle pieniä juomasarvia
ja astioita, joissa oli kallio-imarretta ja kuivattuja marjoja. Jokaisessa
astiassa oli vain yksi marja.
"Minua ei peijaa kukaan", sanoi peikkojen kuningas ovelan
näköisenä, täytettyään parisen kertaa sarvensa muutamilla tipoilla
makeata vierrettä, jota oli käyty taloista näpistelemässä. Sarvi ei
ollut suurempi lapsenhansikkaan pikkusormea. "Minä olen niin
vanha, että olen nähnyt kahden ikämetsän lahoovan, ja tiedän myös,
kuka sinä olet, pikku herttua. Koko maa on kerran oleva sinun, jos
vain saat elää. Minne sinä nyt ratsastat kaksijalkaisella hevosellasi?"
"Eerikki Menvedin luo", vastasi Maunu.
"Onko se joku rikas talonpoika?"
"Ei suinkaan, peikko-ukkoseni. Eerikki Menved on ritarikuningas.
Muistelehan, mitä olet kuullut kerrottavan iso-isästäni, kuuluisasta
ritarista Maunu Latolukosta. Siitä pääset selville, millainen se
Eerikki Menvedkin on."

"Koetetaan, koetetaan", vastasi ukko ja siveli partaansa. "Tämä
tyttönen tässä ei sekään ole meidän maahisten tytär, ja hän
kasvaakin niin rutosti, ettei hän kohta enää sovi maamajaamme.
Miten on meidän silloin menetteleminen? Ikävintä teissä
ihmislapsissa on, että te kasvatte niin suuriksi."
"Minä saanen kai tulla noutamaan hänet täältä", huusi Maunu niin
kovaa ja rohkeasti, että uskollinen Arvid heräsi. Pelästyneenä tarttui
hän suojattiaan jaloista, jotka näkyivät kummusta ja nosti hänet
selkäänsä. Mutta Maunu piirteli tuon tuostakin tikarillaan merkkejä
kuusenrunkoihin.
Cicilla seurasi murheellisin katsein uutta leikkitoveriansa, kun tämä
katosi puiden taa. Ensikerran oli hän nyt nähnyt ihmisen, ensikerran
siitä, kun hän oli alkanut kasvaa. Ja nyt ymmärsi hän, että hänellä
itselläänkin oli ihmisen sielu. Siitä hetkestä lähtien ei hän enää
viihtynyt köntysmäisen kääpiökansan parissa, vaan kuljeskeli usein
yksinään.
Eräänä iltana otti hän hopeamaljansa piilostaan. Peikot olivat
sanoneet: "Jos sinä joskus haluat saada vastauksen kysymykseen,
jota sinä hartaasti ajattelet, niin mene silloin juuri päivän ja yön
erotessa toisistaan lähteelle, mistä ei kukaan ihminen ole vielä
juonut ja täytä maljasi vedellä." Hän tiesi kyllä, missä semmoinen
kirkas ja tyyni lähde oli korkeiden kallioiden välistä löydettävissä.
Varovasti taivutti hän sananjalat sivulle ja täytti maljan ikiselkeällä
vedellä.
Silloin alkoi maljan pohjasta tuikkia omituinen kimallus, ja
ikäänkuin pienestä akkunaisesta näki hän ihanaan saliin, joka oli
täynnä ritareita. Muuan jalon näköinen ylimys, jonka piirteet olivat
hyvin murheelliset, istui kunnia-istuimella ja piteli Maunua polvillaan.

"Tuo on varmaankin Eerikki Menved", ajatteli hän. "Nyt on Maunu
saanut hyvän isän. Enpä ihmettelisi, vaikka hän olisi minut
unohtanutkin." Kunnia-istuimen edessä seisoi Arvid Smålantilainen ja
kertoi itkien jotakin. Cicilla kurottautui paremmin nähdäkseen, mutta
samassa sammui viimeinenkin päivänsäde kuusten latvoista, ja vesi
kuvasti vain tyhjän, kylmänharmaan taivaan. Silloin pisti hän maljan
vyöhönsä ja nyyhkytti itsekseen: "Raskasta on istua yksinään, kun
aurinko metsässä kulkee."
MÄRTA-KUNINGATAR NAURAA.
Birgeriä ja hänen kuningatartansa pidettiin vankeina Nyköpingin
linnassa, mutta kun Eerikki Menved varustautui ritareineen tulemaan
heidän avukseen, pääsivät he vapaiksi. Mutta epäsopu vallitsi yhä
veljesten kesken, ja herttuat ottivat Birgeriltä suurimman osan hänen
valtakuntaansa. Riideltyään sitten monet Herran vuodet, päättivät he
vihdoin kaikki yhteisesti, että nyt piti tuleman heidän välilleen rauha
ja sopu. Mutta kuningatar Märta uneksi hiljaisuudessa tykkänään
toista. Hän halusi keksiä koston, jota ei hevin unohdettaisi, ja siksi
lähetti hän sanan noita-akoille metsään. Trulla-Ho pani silloin suitset
vasikan päähän ja ratsasti Nyköpingin linnaan.
Siellä vietiin hänet vankilaan. Portailla tuli kuningatar häntä
vastaan, sylissä seula, joka oli täynnä riepuja. Hänen takanaan seisoi
Birger kädet polvien välissä, hehkuen uteliaisuutta. "Jos sinussa on
vähänkin noidan vikaa", sanoi kuningatar, "niin ammu taikanuoli
herttua Eerikkiin, niin että hän kaatuu maahan ja kuolee!"
Trulla-Ho teki silloin rievuista nuken, jonka hän kastoi sannalla
Eerikiksi, ja sitten tuotiin hänelle joutsi ja leppänuoli. Mutta kun
hänen piti ampuman tuhoava nuoli nukkeen, risahti joutsi. Hän

änkytti: "En voi. Suo anteeksi, Märta-kuningatar, en voi. Herttua on
vihitty ritari, häneen ei minun nuoleni pysty." Kuningatar heitti
vihoissaan seulan maahan. "Pysy sitten siellä, missä oletkin. Minä
keksin itse paremman keinon", sanoi hän ja hävisi kuninkaan kanssa
linnaan.
Alhaalla holvissa oli paljon noita-akkoja ja muita vankeja. Päivät
päästään seisoivat he ristikko-akkunassa ja ulisivat ja kerjäsivät
leivänpalaa vahtimiesten kulkiessa ohi. Siinä saivat he myös kuulla
uutisia kaikista tapahtumista, ja puheina eivät olleetkaan nyt
mitkään tavalliset asiat. Herttua Valdemar, joka ei pitkään aikaan
ollut tavannut heimolaisiansa, tuli vihdoinkin vieraisille heidän
luokseen, ja kun hänen piti jälleen matkustaman pois, seisoi
kuningatar hevosen vieressä ja pyyhkieli silmiään. "Unohtakaamme
kaikki vanhat vihat", nyyhkytti hän. "Suuresti surettaa minua, sano
niin Eerikille, että Birger ja minä niin harvoin saamme tavata häntä.
Jumala tietäköön, että minä rakastan häntä kuin omaa veljeäni."
Valdemar toi siis kerran Eerikin mukanaan, ja vähää ennen joulua
ratsastivat molemmat veljet linnanportista sisään. "Varoituksia ei ole
puuttunut", sanoi Eerikki ja kopahutti veitikkamaisesti miekkaansa.
"Se vain virkistää ritarisydäntä ja tuo kemuihin mainion janon. Anna
pienten piipattaa!"
Birger tuli heitä portailla avosylin vastaan ja johdatti niin
kumpaisenkin kädestä pitäen ylös saliin. Juhlapukuiset palvelijat
kantoivat viiniä ja simaa ja lukemattomia ruokalajeja, ja kynttilöitä ei
voitu laskea. Ja niin alkoivat Nyköpingin pidot torventoitotuksin ja
rummunpärinöin.
"Kuka nauraa?" kyselivät vangit toisiltaan alhaalla holvissa.
"Harvoin saa kuulla naurettavan niin paljon ja niin sydämellisesti."

Trulla-Ho vastasi: "Minä tunnen äänen. Se on Märta-kuningatar.
Sama, jonka muutoin on niin vaikeata hymyillä! Aavistanpa kyllä,
mitä kuningas tänä iltana pani mesijuomaan. Sen mausteen sai hän
minulta."
Kun tuli myöhä, menivät herttuoiden miehet majapaikkoihinsa
kaupunkiin, mutta heidän satulansa ja varustuksensa ja aseensa
jäivät linnan tupaan. Drotsi Brunke kuljeskeli avainkimppu vyössään
julmana, pelkäämättömänä, käskevänä, mutta Birgerille uskollisena.
Hänen vaatteensa olivat pöhöllään, kuin olisi hän lyönyt selkäänsä
neljät turkit, koukkunenä heilui korkealla ilmassa ja kypärä valkoisine
sulkatöyhtöineen luisui alas niskaan. Kun viimeinen mies oli
poistunut linnasta, sulki hän portin. "Kuningas Birger", sanoi hän
samassa, sillä hän näki varjon liukuvan ohitseen muuria pitkin.
"Täällä sinä harhailet neuvottomana pitkin pihoja ja jäähdytät
otsaasi, siksi kunnes unohdat koston, jota hiljaa vannoit yhä
uudelleen jokaisella simakulauksella. Iske tänä yönä. Muuten ehkä
olet sinä seuraavissa pidoissa se, joka lyödään rautoihin."
Hän pisti kätensä kuninkaan kainaloon ja vei hänet muassaan
linnaan. Hetkisen oli kaikki hiljaa. Vangit luulivat, ettei mitään enää
tapahtuisikaan sinä yönä, ja alkoivat kahmia kokoon olkia
yösijakseen.
Silloin leimahtivat yht'äkkiä soihdut herttuain makuukammion
käytävässä, ja miekat kalisivat toisiaan vasten. "Herkeä, herkeä, veli
Valdemar, tässä ei auta tappelu!" kuului Eerikki huutavan. Pian
astelivatkin herttuat vankilan rappuja, vartioiden ympäröiminä,
paljain jaloin ja sidotuin käsin. He olivat sipaisseet takit ylleen, mutta
muita vaatteita ei heillä ollut, ja heidän takanaan kiljui Birger

tuijottavin silmin: "Muistatteko Håtunan temppua, muistatteko
Håtunan temppua!"
Heidät suljettiin holviin, ja päivän sarastaessa tuotiin sinne myös
heidän miehensä kaupungista. Kaikki, noin parikymmentä
kappaletta, kytkettiin samaan hirteen. Pihalla oli aika markkinat.
Siellä istui koko linnan väki piirissä lyömässä arpaa heidän
hevosistaan ja varustuksistaan. Toiset tutkistelivat heidän
matkasäkkejään. Kuningas Birger paukutti käsiään ja huusi kuin
hullu: "Siunatkoon Pyhä Henki kuningatartani! Nyt on Ruotsi minun!"
Seuraavina päivinä kuiskivat Brunke ja kuningatar monta häijyä
neuvoa hänen korvaansa. Vihdoin muutatti hän veljensä vielä
kamalampaan vankilaan tornin syvimpään luolaan paljaalle kalliolle.
Heidät kahlehdittiin muuriin kummallekin puolelle haisevaa
vesilätäkköä. Ja kun pölkkyjä uudelleen lyötiin Eerikin jalkoihin, lensi
säle hänen silmäänsä, niin että veri valui pitkin poskea.
Vangit näkivät ristikko-akkunastaan, miten Birger ratsasti linnasta
asejoukkoineen, mutta kun hän palasi takaisin, oli hänen
naurunhalunsa loppunut. Tukholmassa olivat porvarit sulkeneet
kaupungin portit hänen nenänsä edestä ja ajaneet hänet pakosalle
yli pohjoisen nummen. Kylästä kylään, talosta taloon oli lentänyt
huhu Nyköpingin pidoista ja herttuain kovasta kohtalosta. Heidän
ystävänsä, Matti Kättilmundinpoika ja laamanni Birger Pietarinpoika
Finnstadista ja muut valtakunnan jaloimmat miehet nostattivat
rohkeasti länsigötalaisia, upplantilaisia ja smålantilaisia kapinaan.
Birger seisoi linnansa pihalla olkapäät koholla ja tempoili
rautahansikkaitaan. Väliin loi hän katseensa alas santaan, väliin ylös
pilviin. "Satuloikaa hevoset", käski hän epävarmasti. "Stegeborgissa
on lujat muurit ja hyvä satama purjelaivoille, jos lopultakin kävisi

kehnosti. Minä halveksin vihollisiani ja kaikkia entisen maani
asukkaita."
"Halveksunta" — Brunke asettui hänen eteensä kädet puuskassa
— "on heikkojen miesten ja velttojen huulten sana. Sitä käyttävät
eniten ne, jotka ovat saaneet häpeän haltuunsa ja jotka eivät voi
mitään muuta vastata. Se on hävinneen sana, eikä koskaan
voittajan. Ole iloissasi, että minä osaan käytellä miekkaani silloin,
kun sinä mielettömänä pelosta kömmit hevosesi selkään, halveksiva
hymy huulillasi ja pakenet täyttä laukkaa."
"Hän luulee minun epäröivän", mutisi Birger ja kääntyi poispäin.
Kasvot hehkuvan punaisina meni hän sitten torniin ja käänsi avainta
useampaan kertaan lukossa, siksi kunnes ovi oli täydellisesti suljettu.
Sitten singahutti hän kiukkuisen voimakkaasti avaimen jokeen, joka
tummana ja syvänä juoksi siellä jyrkän vallin juurella.
Haudan hiljaisuuden vallitessa nousi hän sitten hevosensa selkään,
asettui kuningattaren ja Brunken väliin ja kiiruhti pois koko hovinsa
kanssa.
Vielä jonkun aikaa kuulivat vangit herttuain puhelevan keskenään
alhaalla holvissa, mutta sitten muuttui kaikki hiljaiseksi. Silloin oli
täysi kesä, ja kapinallisen sotajoukon aseet välkkyivät jo läheisillä
kukkuloilla. Linnanpäällikkö mursi silloin tornin lukon ja toi holvista
herttuain kuihtuneet, hengettömät ruumiit. Ne pantiin paareille, jota
peitti kultavaate. Sitten vietiin ne piirittäjäin nähtäville, jotta he
voisivat omin silmin vakuuttautua siitä, että heidän taistelunsa nyt oli
turha. Oliko tuo tuossa ylväs herttua Eerikki, joka virui siinä niin
vanhentuneena ja ränsistyneenä? Kauhun valtaamina tunkeutuivat
he paarien ympärille ja vannoivat, ettei koko Nyköpingin linnasta
pitänyt jäämän kiveä kiven päälle.

Welcome to our website – the perfect destination for book lovers and
knowledge seekers. We believe that every book holds a new world,
offering opportunities for learning, discovery, and personal growth.
That’s why we are dedicated to bringing you a diverse collection of
books, ranging from classic literature and specialized publications to
self-development guides and children's books.
More than just a book-buying platform, we strive to be a bridge
connecting you with timeless cultural and intellectual values. With an
elegant, user-friendly interface and a smart search system, you can
quickly find the books that best suit your interests. Additionally,
our special promotions and home delivery services help you save time
and fully enjoy the joy of reading.
Join us on a journey of knowledge exploration, passion nurturing, and
personal growth every day!
ebookbell.com