Skip to content

Commit

Permalink
Merge pull request #40 from pedropark99/dev-fixes
Browse files Browse the repository at this point in the history
Add some fixes and a contributors list to the project
  • Loading branch information
pedropark99 authored Sep 16, 2024
2 parents dbb3a3b + da7fa1a commit 83404cc
Show file tree
Hide file tree
Showing 12 changed files with 379 additions and 279 deletions.
56 changes: 27 additions & 29 deletions Chapters/01-base64.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -257,38 +257,32 @@ For the encoder, the logic is the following: for each 3 bytes that we find in th
by 3, use a ceiling function, then, we multiply the result by 4. That way, we get the total
number of bytes that will be produced by the encoder in it's output.

The `_calc_encode_length()` function below encapsulates this logic. Notice that we convert
the `.len` property of the array, which is always a integer (more precisely, an `usize` value),
into a floating point number of 64 bits (`f64`). We do this, because the ceiling function (`@ceil()`) works
only with floating point numbers. So, we convert it so that the division with the number `3.0` results in
a floating point number. Then, after the ceiling process, we can convert the result back into an
integer value (with the `@intFromFloat()` function).
The `_calc_encode_length()` function below encapsulates this logic.
Inside this function, we take the length of the input array,
we divide it by 3, and apply a ceil operation over the result by using the
`divCeil()` function from the Zig Standard Library. Lastly, we multiply
the end result by 4 to get the answer we need.

```{zig}
#| auto_main: false
#| build_type: "lib"
fn _calc_encode_length(input: []const u8) u64 {
const std = @import("std");
fn _calc_encode_length(input: []const u8) !usize {
if (input.len < 3) {
const n_output: u64 = 4;
const n_output: usize = 4;
return n_output;
}
const len_as_float: f64 = @floatFromInt(input.len);
const n_output: u64 = @intFromFloat(@ceil(len_as_float / 3.0) * 4.0);
return n_output;
const n_output: usize = try std.math.divCeil(
usize, input.len, 3
);
return n_output * 4;
}
```

Is important to notice that, when I am using the built-in functions from Zig to convert data types (`@floatFromInt()` and `intFromFloat()`),
I'm always annotating explicitly the type of the variable that stores the result of these functions.
I do that, because these functions need this information. `@floatFromInt()` needs to know
which type of floating point number I want to use in it's output. Is it `f16`? `f32`? `f64`? etc.
The same goes to `@intFromFloat()`.

Also, you might have notice that, if the input length is less than 3 bytes, then, the output length of the encoder will
be always 4 bytes. This is because the algorithm will always fill the gap in the input with zeroes, until it fits
the window of 24 bits that the algorithm likes to work on, as I described at @sec-base64-encoder-algo. So the output
of the algorithm will always be 4 bytes in this specific case.

Also, you might have notice that, if the input length is less than 3 bytes, then, the output length of the encoder is
always 4 bytes. This is the case for every input with less than 3 bytes, because, as I described at @sec-base64-encoder-algo,
the algorithm always produces enough "padding-groups" in the end result, to complete the 4 bytes window.

Now, for the decoder, we just need to apply the inverse logic: for each 4 bytes in the input, 3 bytes
will be produced in the output of the decoder. I mean, this is roughly true, because we also need to
Expand All @@ -297,20 +291,24 @@ at @fig-base64-algo2. But we can ignore this fact for now, to make things simple

So, the function `_calc_decode_length()` summarizes this logic that we described. It is very similar
to the function `_calc_encode_length()`, only the division part is twisted, and also, in the special
case where we have less than 4 bytes in the input to work on.
case where we have less than 4 bytes in the input to work on. Also notice that this time, we apply
a floor operation over the output of the division, by using the `divFloor()`
function (instead of `divCeil()`).


```{zig}
#| auto_main: false
#| build_type: "lib"
fn _calc_decode_length(input: []const u8) u64 {
const std = @import("std");
fn _calc_decode_length(input: []const u8) !usize {
if (input.len < 4) {
const n_output: u64 = 3;
const n_output: usize = 3;
return n_output;
}
const len_as_float: f64 = @floatFromInt(input.len);
const n_output: u64 = @intFromFloat(@floor(len_as_float / 4.0) * 3.0);
return n_output;
const n_output: usize = try std.math.divFloor(
usize, input.len, 4
);
return n_output * 3;
}
```

Expand Down Expand Up @@ -604,7 +602,7 @@ pub fn encode(self: Base64,
return "";
}
const n_out = _calc_encode_length(input);
const n_out = try _calc_encode_length(input);
var out = try allocator.alloc(u8, n_out);
var buf = [3]u8{ 0, 0, 0 };
var count: u8 = 0;
Expand Down Expand Up @@ -808,7 +806,7 @@ fn decode(self: Base64,
if (input.len == 0) {
return "";
}
const n_output = _calc_decode_length(input);
const n_output = try _calc_decode_length(input);
var output = try allocator.alloc(u8, n_output);
for (output, 0..) |_, i| {
output[i] = 0;
Expand Down
42 changes: 39 additions & 3 deletions Chapters/03-structs.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ pub fn main() !void {
}
```


#### Switch statements exhaust all possibilities

Now, one very important aspect about this switch statement presented
in the code example above, is that it exhaust all existing possibilities.
In other words, all possible values that could be found inside the `order`
Expand All @@ -165,12 +168,17 @@ a switch statement, and leave an edge case with no expliciting action to be take
This is a similar behaviour to switch statements in Rust, which also have to
handle all possible cases.



#### The else branch

Take a look at the `dump_hex_fallible()` function below as an example. This function
also comes from the Zig Standard Library, but this time, it comes from the [`debug.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/debug.zig)[^debug-mod].
also comes from the Zig Standard Library, but this time, it comes from the
[`debug.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/debug.zig)[^debug-mod].
There are multiple lines in this function, but I omitted them to focus solely on the
switch statement found in this function. Notice that this switch statement have four
possible cases, or four explicit branches. Also, notice that we used an `else` branch
in this case. Whenever you have multiple possible cases in your switch statement
in this case. Whenever you have multiple cases in your switch statement
which you want to apply the same exact action, you can use an `else` branch to do that.

[^debug-mod]: <https://github.com/ziglang/zig/blob/master/lib/std/debug.zig>
Expand Down Expand Up @@ -222,14 +230,18 @@ t.zig:9:13: 0x1033c58 in main (switch2)
^
```



#### Using ranges in switch

Furthermore, you can also use ranges of values in switch statements.
That is, you can create a branch in your switch statement that is used
whenever the input value is contained in a range. These range
expressions are created with the operator `...`. Is important
to emphasize that the ranges created by this operator are
inclusive on both ends.

For example, I could easily change the code example above to support all
For example, I could easily change the previous code example to support all
levels between 0 and 100. Like this:

```{zig}
Expand All @@ -252,6 +264,30 @@ simply write `'a'...'z'`, to match any character value that is a
lowercase letter, and it would work fine.


#### Labeled switch statements

At @sec-blocks we have talked about labeling blocks, and also, about using these labels
to return a value from the block. Well, from version 0.14.0 and onwards of the `zig` compiler,
you can also apply labels over switch statements,
which makes possible to implement almost a "C goto like" pattern in Zig.

For example, if you give the label `xsw` to a switch statement, you can use this
label in conjunction with the `continue` keyword to go back to the beginning of the switch
statement. In the example below, the execution goes back to the beginning of the
switch statement two times, before ending at the `3` branch.

```{zig}
#| auto_main: false
#| build_type: "lib"
#| eval: false
xsw: switch (@as(u8, 1)) {
1 => continue :xsw 2,
2 => continue :xsw 3,
3 => return,
4 => {},
}
```


### The `defer` keyword {#sec-defer}

Expand Down
24 changes: 11 additions & 13 deletions ZigExamples/base64/base64_basic.zig
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ const Base64 = struct {
if (input.len == 0)
return "";

const n_output = _calc_encode_length(input);
const n_output = try _calc_encode_length(input);
var output = try allocator.alloc(u8, n_output);
var tmp_buffer = [3]u8{ 0, 0, 0 };
var count: u8 = 0;
var output_index: u64 = 0;
var output_index: usize = 0;

for (input, 0..) |_, i| {
tmp_buffer[count] = input[i];
Expand Down Expand Up @@ -80,7 +80,7 @@ const Base64 = struct {
if (input.len == 0)
return "";

const n_output = _calc_decode_length(input);
const n_output = try _calc_decode_length(input);
var tmp_buffer = [4]u8{ 0, 0, 0, 0 };
var output = try allocator.alloc(u8, n_output);
var count: u8 = 0;
Expand Down Expand Up @@ -109,25 +109,23 @@ const Base64 = struct {
}
};

fn _calc_encode_length(input: []const u8) u64 {
const len_as_float: f64 = @floatFromInt(input.len);
fn _calc_encode_length(input: []const u8) !usize {
if (input.len < 3) {
const n_output: u64 = 4;
const n_output: usize = 4;
return n_output;
}

const n_output: u64 = @intFromFloat(@ceil(len_as_float / 3.0) * 4.0);
return n_output;
const n_output: usize = try std.math.divCeil(usize, input.len, 3);
return n_output * 4;
}

fn _calc_decode_length(input: []const u8) u64 {
const len_as_float: f64 = @floatFromInt(input.len);
fn _calc_decode_length(input: []const u8) !usize {
if (input.len < 4) {
const n_output: u64 = 3;
const n_output: usize = 3;
return n_output;
}
const n_output: u64 = @intFromFloat(@floor(len_as_float / 4.0) * 3.0);
return n_output;
const n_output: usize = try std.math.divFloor(usize, input.len, 4);
return n_output * 3;
}

pub fn main() !void {
Expand Down
4 changes: 2 additions & 2 deletions _freeze/Chapters/01-base64/execute-results/html.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions _freeze/Chapters/03-structs/execute-results/html.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions _freeze/index/execute-results/html.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"hash": "59aac007bbff258bb5af0e77915366c8",
"hash": "87da007e8766ae15b718d8b3223b480f",
"result": {
"engine": "knitr",
"markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n::: {.content-visible when-format=\"html\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## About this book {.unnumbered}\n\nThis an open book, meaning that, it is open-source, and it will always be open\nfor anyone that wants to read it. However, this book is still under construction 🚧 and active development,\nso, it's contents might change drastically in the near future.\n\nAlso, this is a project-based book, which means that we learn how to use the Zig programming language\nthrough small and simple projects, in a similar style to the famous \"Python Crash Course\" book from Eric Matthes.\n\nOfficial book's repository: <https://github.com/pedropark99/zig-book>\n\n:::\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria have a bachelor degree in Economics from Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\nan Associate Developer for Apache Spark 3.0 certified by Databricks.\n\n[^blip]: <https://www.blip.ai/en/>\n\n\nThe author have more than 4 years of experience in the data industry. Developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nbrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer that loves to\nlearn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[<https://ppea.ufop.br/>]),\nin addition to federal and state organizations (such as FJP-MG^[<http://fjp.mg.gov.br/>]).\n\n\nPersonal Website: <https://pedro-faria.netlify.app/>\n\nLinkedin: <https://www.linkedin.com/in/pedro-faria-a68140209/>\n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2024 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: <https://creativecommons.org/licenses/by/4.0/>\n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n- System version: Linux, 6.8.0-44-generic, NA, x86_64.\n\n- Zig version: 0.14.0-dev.1166+bb7050106.\n\n- Quarto version: 1.5.56.\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {December},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://pedropark99.github.io/zig-book/}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: <https://pedro-faria.netlify.app/>\n",
"markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n::: {.content-visible when-format=\"html\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## About this book {.unnumbered}\n\nThis an open book, meaning that, it is open-source, and it will always be open\nfor anyone that wants to read it. However, this book is still under construction 🚧 and active development,\nso, it's contents might change drastically in the near future.\n\nAlso, this is a project-based book, which means that we learn how to use the Zig programming language\nthrough small and simple projects, in a similar style to the famous \"Python Crash Course\" book from Eric Matthes.\n\nOfficial book's repository: <https://github.com/pedropark99/zig-book>\n\n:::\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria have a bachelor degree in Economics from Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\nan Associate Developer for Apache Spark 3.0 certified by Databricks.\n\n[^blip]: <https://www.blip.ai/en/>\n\n\nThe author have more than 4 years of experience in the data industry. Developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nbrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer that loves to\nlearn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[<https://ppea.ufop.br/>]),\nin addition to federal and state organizations (such as FJP-MG^[<http://fjp.mg.gov.br/>]).\n\n\nPersonal Website: <https://pedro-faria.netlify.app/>\n\nLinkedin: <https://www.linkedin.com/in/pedro-faria-a68140209/>\n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2024 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: <https://creativecommons.org/licenses/by/4.0/>\n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n\n- System version: Linux, 6.8.0-44-generic, NA, x86_64.\n\n- Zig version: 0.14.0-dev.1166+bb7050106.\n\n- Quarto version: 1.5.56.\n\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {December},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://pedropark99.github.io/zig-book/}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: <https://pedro-faria.netlify.app/>\n\n\n## Acknowledgments\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton)\n",
"supporting": [],
"filters": [
"rmarkdown/pagebreak.lua"
Expand Down
7 changes: 5 additions & 2 deletions contributors.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
name,user_name,
Calin Martinconi,@martinconic,
name,user_name
Calin Martinconi,@martinconic
Steffen Roller,@sroller
Chris Boesch,@chrboesch
Lv Sihan,@Pokryton
Loading

0 comments on commit 83404cc

Please sign in to comment.