Marcin Jahn | Dev Notebook
  • Home
  • Programming
  • Technologies
  • Projects
  • About
    cirro.services
  • Home
  • Programming
  • Technologies
  • Projects
  • About
  • An icon of the .NET section.NET
    • HTTPClient
    • Async
      • How Async Works
      • TAP Tips
    • Equality
    • Comparisons
    • Enumerables
    • Unit Tests
    • Generic Host
    • Logging
    • Configuration
    • Records
    • Nullability
    • Garbage Collector
    • IL and Allocations
    • gRPC
    • Platform Invoke
    • ASP.NET Core
      • Overview
      • Middleware
      • Razor Pages
      • Routing in Razor Pages
      • Web APIs
      • Filters
      • Identity
      • Validation
      • Tips
    • Entity Framework Core
      • Overview
      • Testing
      • Tips
  • An icon of the Angular sectionAngular
    • Overview
    • Components
    • Directives
    • Services and DI
    • Routing
    • Observables (RxJS)
    • Forms
    • Pipes
    • HTTP
    • Modules
    • NgRx
    • Angular Universal
    • Tips
    • Standalone Components
  • An icon of the JavaScript sectionJavaScript
    • OOP
    • JavaScript - The Weird Parts
    • JS Functions
    • ES Modules
    • Node.js
    • Axios Tips
    • TypeScript
      • TypeScript Environment Setup
      • TypeScript Tips
    • React
      • React Routing
      • MobX
    • Advanced Vue.js Features
  • An icon of the Rust sectionRust
    • Overview
    • Cargo
    • Basics
    • Ownership
    • Structures
    • Enums
    • Organization
    • Collections
    • Error Handling
    • Generics
    • Traits
    • Lifetimes
    • Closures
    • Raw Pointers
    • Smart Pointers
    • Concurrency
    • Testing
    • Tips
  • An icon of the C/C++ sectionC/C++
    • Structs and Classes
    • Compilation
    • Pointers
    • Strings
    • Dynamic Memory
    • argc and argv Visualization
  • An icon of the GTK sectionGTK
    • Overview
    • GJS
  • An icon of the CSS sectionCSS
    • Responsive Design
    • CSS Tips
    • CSS Pixel
  • An icon of the Unity sectionUnity
    • Unity
  • An icon of the Functional Programming sectionFunctional Programming
    • Fundamentals of Functional Programming
    • .NET Functional Features
    • Signatures
    • Function Composition
    • Error Handling
    • Partial Application
    • Modularity
    • Category Theory
      • Overview
      • Monoid
      • Other Magmas
      • Functors
  • An icon of the Algorithms sectionAlgorithms
    • Big O Notation
    • Array
    • Linked List
    • Queue
    • Hash Table and Set
    • Tree
    • Sorting
    • Searching
  • An icon of the Architecture sectionArchitecture
    • What is architecture?
    • Domain-Driven Design
    • ASP.NET Core Projects
  • An icon of the .NET section.NET
    • HTTPClient
    • Async
      • How Async Works
      • TAP Tips
    • Equality
    • Comparisons
    • Enumerables
    • Unit Tests
    • Generic Host
    • Logging
    • Configuration
    • Records
    • Nullability
    • Garbage Collector
    • IL and Allocations
    • gRPC
    • Platform Invoke
    • ASP.NET Core
      • Overview
      • Middleware
      • Razor Pages
      • Routing in Razor Pages
      • Web APIs
      • Filters
      • Identity
      • Validation
      • Tips
    • Entity Framework Core
      • Overview
      • Testing
      • Tips
  • An icon of the Angular sectionAngular
    • Overview
    • Components
    • Directives
    • Services and DI
    • Routing
    • Observables (RxJS)
    • Forms
    • Pipes
    • HTTP
    • Modules
    • NgRx
    • Angular Universal
    • Tips
    • Standalone Components
  • An icon of the JavaScript sectionJavaScript
    • OOP
    • JavaScript - The Weird Parts
    • JS Functions
    • ES Modules
    • Node.js
    • Axios Tips
    • TypeScript
      • TypeScript Environment Setup
      • TypeScript Tips
    • React
      • React Routing
      • MobX
    • Advanced Vue.js Features
  • An icon of the Rust sectionRust
    • Overview
    • Cargo
    • Basics
    • Ownership
    • Structures
    • Enums
    • Organization
    • Collections
    • Error Handling
    • Generics
    • Traits
    • Lifetimes
    • Closures
    • Raw Pointers
    • Smart Pointers
    • Concurrency
    • Testing
    • Tips
  • An icon of the C/C++ sectionC/C++
    • Structs and Classes
    • Compilation
    • Pointers
    • Strings
    • Dynamic Memory
    • argc and argv Visualization
  • An icon of the GTK sectionGTK
    • Overview
    • GJS
  • An icon of the CSS sectionCSS
    • Responsive Design
    • CSS Tips
    • CSS Pixel
  • An icon of the Unity sectionUnity
    • Unity
  • An icon of the Functional Programming sectionFunctional Programming
    • Fundamentals of Functional Programming
    • .NET Functional Features
    • Signatures
    • Function Composition
    • Error Handling
    • Partial Application
    • Modularity
    • Category Theory
      • Overview
      • Monoid
      • Other Magmas
      • Functors
  • An icon of the Algorithms sectionAlgorithms
    • Big O Notation
    • Array
    • Linked List
    • Queue
    • Hash Table and Set
    • Tree
    • Sorting
    • Searching
  • An icon of the Architecture sectionArchitecture
    • What is architecture?
    • Domain-Driven Design
    • ASP.NET Core Projects

Structures

Structs are like structs/classes in other languages. Structs have fields. We can instantiate structs.

struct User {
  active: bool,
  username: String,
  email: String,
  age: u32
}

let user1 = User {
  email: String::from("user1@gmail.com"),
  username: String::from("user1"),
  active: true,
  age: 20
};

Only mutable instances may be mutated:

let mut user2 = User {
  email: String::from("user2@gmail.com"),
  username: String::from("user2"),
  active: true,
  age: 19
};

user2.active = false;

Stack

By default, Rust stores all data on the stack (like C/C++). Struct instances also are stored on the stack. Smart pointers allow changing that.

Only types whose size is known at compile time can be stored on the stack.

Shortcuts

A bit like in JS, we can use the shorter way to instantiate objects:

fn create_object(username: String, email: String) -> User {
  User {
    username,
    email, // or email: email
    active: false,
    age: 100
  }
}

Also, we can create an instances based on other instances:

let user3 = User {
  email: String::from("user3@example.com"),
  ..user2 // must come last
};

Move

user2 was moved in the example above. Since username is a String, it was moved to user3. If the only values that were copied from user2 were active and age, there would be no move. They’d be just copied.

Tuple Structs

Tuples may be defined with a name, like this:

struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);

The fields don’t have names, sometimes it’s ok for simple types.

Unit-like Structs

Structs may be completely empty:

struct AlwaysEqual;

let subject = AlwaysEqual;

It’s useful with traits.

Methods

Methods are defined outside of struct definition:

struct Rectangle {
  width: u32,
  height: u32,
}

impl Rectangle {
  fn area(&self) -> u32 {
    self.width * self.height
  }

  fn can_hold(&self, other: &Rectangle) -> bool {
    self.width > other.width && self.height > other.height
  }
}

The first paramtere of a method is &self. It’s a sugar syntax for self: &Self. We could also not use reference, or add mut. The first case is rare because it would take ownership. It could be useful if a method is supposed to transform an object info something else end the original object would not be needed anymore.

Impl blocks

There may be more than one impl blocks per type.

We can invoke methods like this:

let r = Rectangle();
let area = r.area(); // or Rectangle::area(&r); 

Static methods

Methods may be defined as non-associated if they do not require an actual instance of a type. In such a case, there is no need for the first parameter to be Self. Example of such a function is String::from(). It’s also useful for constuctors.

←  Ownership
Enums  →
© 2023 Marcin Jahn | Dev Notebook | All Rights Reserved. | Built with Astro.