Skip to content

Commit

Permalink
doc: Update book
Browse files Browse the repository at this point in the history
  • Loading branch information
mcmah309 committed Jun 29, 2024
1 parent 3c8b699 commit addc673
Show file tree
Hide file tree
Showing 13 changed files with 412 additions and 283 deletions.
7 changes: 1 addition & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,12 @@
[![Pub Version](https://img.shields.io/pub/v/rust_core.svg)](https://pub.dev/packages/rust_core)
[![Dart Package Docs](https://img.shields.io/badge/documentation-pub.dev-blue.svg)](https://pub.dev/documentation/rust_core/latest/)
[![License: MIT](https://img.shields.io/badge/license-MIT-purple.svg)](https://opensource.org/licenses/MIT)
[![Build Status](https://github.com/mcmah309/rust_core/actions/workflows/dart.yml/badge.svg)](https://github.com/mcmah309/rust_core/actions)
[![Build Status](https://github.com/mcmah309/rust_core/actions/workflows/test.yml/badge.svg)](https://github.com/mcmah309/rust_core/actions)

[rust_core](https://github.com/mcmah309/rust_core) is an implementation of Rust's Core Library in Dart, bringing the power of Rust to Dart!

[Rust Core Book 📖](mcmah309.github.io/rust_core)

If you are a Rust developer coming to Dart or vice versa, check out these links:
- [New To Dart](./new_to_dart.md)
- [New To Rust](./new_to_rust.md)


# Project Goals

rust_core's primary goal is to bring Rust's features and ergonomics to Dart.
Expand Down
3 changes: 3 additions & 0 deletions book/book.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ language = "en"
multilingual = false
src = "src"
title = "rust_core"

[output.html]
fold.enable = true
1 change: 1 addition & 0 deletions book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- [option](./libs/option/option.md)
- [panic](./libs/panic/panic.md)
- [result](./libs/result/result.md)
- [Tips and Best Practices](./libs/result/tips_and_best_practices.md)
- [slice](./libs/slice/slice.md)
- [sync](./libs/sync/sync.md)
- [typedefs](./libs/typedefs/typedefs.md)
Expand Down
74 changes: 73 additions & 1 deletion book/src/introduction/new_to_dart.md
Original file line number Diff line number Diff line change
@@ -1 +1,73 @@
# New To Dart
# New To Dart

Welcome to Dart!

Dart is a great language choice for simple yet rich language for fast cross platform development (especially in the ui) and scripting.

rust_core is great start to learn the Dart semantics as you will feel like you are writing native rust. Just look at this Rust code:
> Goal: Get the index of every "!" in a string not followed by a "?"
```rust
use std::iter::Peekable;

fn main() {
let mut answer: Vec<usize> = Vec::new();
let string = "kl!sd!?!";
let chars: Vec<char> = string
.chars()
.collect();
let mut iter: Peekable<_> = chars
.windows(2)
.enumerate()
.peekable();

while let Some((index, window)) = iter.next() {
match window {
['!', '?'] => continue,
['!', _] => answer.push(index),
[_, '!'] if iter.peek().is_none() => answer.push(index + 1),
_ => continue,
}
}
assert_eq!(answer, [2, 7]);
}
```
Dart equivalent with rust_core:
```dart
import 'package:rust_core/prelude';
void main() {
List<int> answer = [];
String string = "kl!sd!?!";
Peekable<(int, Arr<String>)> iter = string
.chars()
.windows(2)
.enumerate()
.peekable();
while (iter.moveNext()) {
final (index, window) = iter.current;
switch (window) {
case ["!", "?"]:
break;
case ["!", _]:
answer.add(iter.current.$1);
case [_, "!"] when iter.peek().isNone():
answer.add(index + 1);
}
}
expect(answer, [2, 7]);
}
```

rust_core will introduce you to a few new types you may find useful as a Dart developer:

| Rust Type | Dart Equivalent | rust_core | Description |
|-------------------|-----------------|----------------------|---------------------------------------------------------|
| `Vec<T>` | `List<T>` | `Vec<T>`* | Dynamic array or list. |
| `[T; N]` | `const [...]`/`List<T>(growable: false)` | `Arr<T>` | Fixed size array or list |
| `Iterator<T>` | `Iterable<T>` | `RIterator<T>` | Composable iteration
| `Option<T>` | `T?` | `Option<T>` | A type that may hold a value or none. |
| `Result<T, E>` | - | `Result<T, E>` | Type used for returning and propagating errors.| |
| `Path` | - | `Path`* | Type for file system path manipulation.
| `[T]` | - | `Slice<T>` | View into an array or list. |
| `Cell<T>` | - | `Cell<T>` | wrappers of values |
*: Implemented through additional packages found [here](../misc/packages_built_on_rust_core.md)
76 changes: 75 additions & 1 deletion book/src/introduction/new_to_rust.md
Original file line number Diff line number Diff line change
@@ -1 +1,75 @@
# New To Rust
# New To Rust

Welcome to Rust!

Maybe you have heard of Rust and want to see what all the hype is about, maybe you know a little Rust
and want to improve your Rust while writing Dart, for whatever the reason, rust_core is here to help.

Rust has a solid reputation for writing safe, maintainable, and performant code. rust_core is great start to learn and improve your rust semantics/knowledge. You will write Dart and learn Rust along the way. Just look at this Dart code:
> Goal: Get the index of every "!" in a string not followed by a "?"
```dart
import 'package:rust_core/prelude';
void main() {
List<int> answer = [];
String string = "kl!sd!?!";
Peekable<(int, Arr<String>)> iter = string
.chars()
.windows(2)
.enumerate()
.peekable();
while (iter.moveNext()) {
final (index, window) = iter.current;
switch (window) {
case ["!", "?"]:
break;
case ["!", _]:
answer.add(iter.current.$1);
case [_, "!"] when iter.peek().isNone():
answer.add(index + 1);
}
}
expect(answer, [2, 7]);
}
```
Rust equivalent:
```rust
use std::iter::Peekable;

fn main() {
let mut answer: Vec<usize> = Vec::new();
let string = "kl!sd!?!";
let chars: Vec<char> = string
.chars()
.collect();
let mut iter: Peekable<_> = chars
.windows(2)
.enumerate()
.peekable();

while let Some((index, window)) = iter.next() {
match window {
['!', '?'] => continue,
['!', _] => answer.push(index),
[_, '!'] if iter.peek().is_none() => answer.push(index + 1),
_ => continue,
}
}
assert_eq!(answer, [2, 7]);
}
```

With rust_core you can expect all the usual types you see in Rust. Here is a quick matrix
comparing Rust, Dart, and Dart with rust_core:

| Rust Type | Dart Equivalent | rust_core | Description |
|-------------------|-----------------|----------------------|---------------------------------------------------------|
| `Vec<T>` | `List<T>` | `Vec<T>`* | Dynamic array or list. |
| `[T; N]` | `const [...]`/`List<T>(growable: false)` | `Arr<T>` | Fixed size array or list |
| `Iterator<T>` | `Iterable<T>` | `RIterator<T>` | Composable iteration
| `Option<T>` | `T?` | `Option<T>` | A type that may hold a value or none. |
| `Result<T, E>` | - | `Result<T, E>` | Type used for returning and propagating errors.| |
| `Path` | - | `Path`* | Type for file system path manipulation.
| `[T]` | - | `Slice<T>` | View into an array or list. |
| `Cell<T>` | - | `Cell<T>` | wrappers of values |
*: Implemented through additional packages found [here](../misc/packages_built_on_rust_core.md)
4 changes: 2 additions & 2 deletions book/src/libs/array/array.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Array

`Arr` (Array) is a zero cost extension type of List, where the list is treated as non-growable. This is useful for correctly handling lists where growable is false and const lists - as these types of lists are treated the same in the regular Dart type system, which may lead to errors.
`Arr` (Array) is a zero cost extension type of `List`, where the list is treated as non-growable. This is useful for correctly handling lists where growable is false and const lists - as these types of lists are treated the same in the regular Dart type system, which may lead to errors.
```dart
var array = Arr(null, 10);
array = Arr.constant(const [1,2,3,4,5]);
Expand All @@ -9,4 +9,4 @@ for(final entry in array){
}
var (slice1, slice2) = array.splitSlice(3);
```
`Arr`'s allocation will be more efficient than compare to a List since it does not reserve additional capacity and allocates the full amount eagerly. Which is important since allocations account for most of the cost of the runtime costs of a List.
`Arr`'s allocation will be more efficient than compare to a `List` since it does not reserve additional capacity and allocates the full amount eagerly. Which is important since allocations account for most of the cost of the runtime costs of a List.
22 changes: 2 additions & 20 deletions book/src/libs/cell/cell.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ expect(newCell, 22);
expect(cell, 12);
expect(antherCell, 10);
```
The base type for all `Cell`s is `ConstCell`.

## OnceCell
A cell which can be written to only once. Similar to `late final <variable>`, but will never throw an error.
Expand All @@ -34,6 +35,7 @@ expect(result, const Ok(()));
result = cell.set(20);
expect(result, const Err(20));
```
The base type for all `OnceCell`s is `NullableOnceCell`.

## LazyCell
A value which is initialized on the first access.
Expand All @@ -51,26 +53,6 @@ final secondCall = lazyCell();
expect(callCount, equals(1));
expect(secondCall, equals(20));
```

## Misc

### Const and Nullability
Most of the time you will not need to know or care about this, and working
with the regular cell types is usually preferred, but
all Cells have `const`, `nullable` and `non-nullable` implementations. These were added for efficiency and to give
more control to developers. e.g. Non-Nullable `OnceCell` and `LazyCell` (which is the default) doesn't need an
additional `bool` to keep track if the value is set.

The base type for all `Cell`s is `ConstCell`.

The base type for all `OnceCell`s is `NullableOnceCell`.

The base type for all `LazyCell`s is `NullableLazyCell`.

`OnceCell` and `LazyCell` have special `constNullable` and `constNonNullable` implementations. These
allow for runtime mutability of the inner value. That opens up a lot of possibilities. e.g.
You can wrap non-const types. Allowing them to be used for something like `@Default(...)`
with the [freezed] package.

[freezed]:https://pub.dev/packages/freezed
[pub]:https://pub.dev/documentation/rust_core/latest/cell/cell-library.html
13 changes: 6 additions & 7 deletions book/src/libs/iter/iter.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,13 @@ Goal: Get the index of every "!" in a string not followed by a "?"
import 'package:rust_core/prelude';
void main() {
List<int> answer = [];
String string = "kl!sd!?!";
PeekableRIterator<(int, Arr<String>)> iter = string.runes
.iter()
.map((e) => String.fromCharCode(e))
.mapWindows(2, (e) => e)
Peekable<(int, Arr<String>)> iter = string
.chars()
.windows(2)
.enumerate()
.peekable();
List<int> answer = [];
while (iter.moveNext()) {
final (int index, Arr<String> window) = iter.current;
switch (window) {
Expand All @@ -67,7 +66,7 @@ void main() {
expect(answer, [2, 7]);
}
```
Rust equivlent
Rust equivalent
```rust
use std::iter::Peekable;

Expand Down Expand Up @@ -126,4 +125,4 @@ This means the iterator can be cloned without cloning the underlying data.
expect(iter3.collectList(), [4, 5]);
expect(iter4.collectList(), [2, 3, 4, 5]);
```
This for allows for situtations where you want to work ahead and not lose your iterator position, or pass the `RIterator` to another function without needing to call e.g. `collectList()`, `collectArr()`, etc.
This for allows for situations where you want to work ahead and not lose your iterator position, or pass the `RIterator` to another function without needing to call e.g. `collectList()`, `collectArr()`, etc.
6 changes: 3 additions & 3 deletions book/src/libs/option/option.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Option represents the union of two types - `Some<T>` and `None`. An `Option<T>` is an extension type of `T?`. Therefore, `Option`
has zero runtime cost and has one big advantage over `T?`, you can chain null specific operations!

All types in rust_core support nullable and `Option` implementations of classes and methods for ergonomic convenience, but you
rust_core support nullable and `Option` implementations of classes and methods for ergonomic convenience where possible, but you
can easily switch between the two with `toOption` and `toNullable` (or you can use `.v` directly).

### Usage
Expand All @@ -23,15 +23,15 @@ You can also use Option in pattern matching
```dart
switch(Some(2)){
case Some(:final v):
// do somthing
// do something
default:
// do something
}
```

### Early Return Key Notation
Option also supports "Early Return Key Notation" (ERKN), which is a derivative of "Do Notation". It allows a
function to return early if the value is `None`, and otherwise safely access the inner value directly without needing to unwrap or typecheck.
function to return early if the value is `None`, and otherwise safely access the inner value directly without needing to unwrap or type check.
```dart
Option<int> intNone() => None;
Option<double> earlyReturn(int val) => Option(($) { // Early Return Key
Expand Down
Loading

0 comments on commit addc673

Please sign in to comment.