Skip to content

Commit 83404cc

Browse files
authored
Merge pull request #40 from pedropark99/dev-fixes
Add some fixes and a contributors list to the project
2 parents dbb3a3b + da7fa1a commit 83404cc

File tree

12 files changed

+379
-279
lines changed

12 files changed

+379
-279
lines changed

Chapters/01-base64.qmd

+27-29
Original file line numberDiff line numberDiff line change
@@ -257,38 +257,32 @@ For the encoder, the logic is the following: for each 3 bytes that we find in th
257257
by 3, use a ceiling function, then, we multiply the result by 4. That way, we get the total
258258
number of bytes that will be produced by the encoder in it's output.
259259

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

267266
```{zig}
268267
#| auto_main: false
269268
#| build_type: "lib"
270-
fn _calc_encode_length(input: []const u8) u64 {
269+
const std = @import("std");
270+
fn _calc_encode_length(input: []const u8) !usize {
271271
if (input.len < 3) {
272-
const n_output: u64 = 4;
272+
const n_output: usize = 4;
273273
return n_output;
274274
}
275-
const len_as_float: f64 = @floatFromInt(input.len);
276-
const n_output: u64 = @intFromFloat(@ceil(len_as_float / 3.0) * 4.0);
277-
return n_output;
275+
const n_output: usize = try std.math.divCeil(
276+
usize, input.len, 3
277+
);
278+
return n_output * 4;
278279
}
279280
```
280281

281-
Is important to notice that, when I am using the built-in functions from Zig to convert data types (`@floatFromInt()` and `intFromFloat()`),
282-
I'm always annotating explicitly the type of the variable that stores the result of these functions.
283-
I do that, because these functions need this information. `@floatFromInt()` needs to know
284-
which type of floating point number I want to use in it's output. Is it `f16`? `f32`? `f64`? etc.
285-
The same goes to `@intFromFloat()`.
286-
287-
Also, you might have notice that, if the input length is less than 3 bytes, then, the output length of the encoder will
288-
be always 4 bytes. This is because the algorithm will always fill the gap in the input with zeroes, until it fits
289-
the window of 24 bits that the algorithm likes to work on, as I described at @sec-base64-encoder-algo. So the output
290-
of the algorithm will always be 4 bytes in this specific case.
291282

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

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

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

302298

303299
```{zig}
304300
#| auto_main: false
305301
#| build_type: "lib"
306-
fn _calc_decode_length(input: []const u8) u64 {
302+
const std = @import("std");
303+
fn _calc_decode_length(input: []const u8) !usize {
307304
if (input.len < 4) {
308-
const n_output: u64 = 3;
305+
const n_output: usize = 3;
309306
return n_output;
310307
}
311-
const len_as_float: f64 = @floatFromInt(input.len);
312-
const n_output: u64 = @intFromFloat(@floor(len_as_float / 4.0) * 3.0);
313-
return n_output;
308+
const n_output: usize = try std.math.divFloor(
309+
usize, input.len, 4
310+
);
311+
return n_output * 3;
314312
}
315313
```
316314

@@ -604,7 +602,7 @@ pub fn encode(self: Base64,
604602
return "";
605603
}
606604
607-
const n_out = _calc_encode_length(input);
605+
const n_out = try _calc_encode_length(input);
608606
var out = try allocator.alloc(u8, n_out);
609607
var buf = [3]u8{ 0, 0, 0 };
610608
var count: u8 = 0;
@@ -808,7 +806,7 @@ fn decode(self: Base64,
808806
if (input.len == 0) {
809807
return "";
810808
}
811-
const n_output = _calc_decode_length(input);
809+
const n_output = try _calc_decode_length(input);
812810
var output = try allocator.alloc(u8, n_output);
813811
for (output, 0..) |_, i| {
814812
output[i] = 0;

Chapters/03-structs.qmd

+39-3
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ pub fn main() !void {
149149
}
150150
```
151151

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

171+
172+
173+
#### The else branch
174+
168175
Take a look at the `dump_hex_fallible()` function below as an example. This function
169-
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].
176+
also comes from the Zig Standard Library, but this time, it comes from the
177+
[`debug.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/debug.zig)[^debug-mod].
170178
There are multiple lines in this function, but I omitted them to focus solely on the
171179
switch statement found in this function. Notice that this switch statement have four
172180
possible cases, or four explicit branches. Also, notice that we used an `else` branch
173-
in this case. Whenever you have multiple possible cases in your switch statement
181+
in this case. Whenever you have multiple cases in your switch statement
174182
which you want to apply the same exact action, you can use an `else` branch to do that.
175183

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

233+
234+
235+
#### Using ranges in switch
236+
225237
Furthermore, you can also use ranges of values in switch statements.
226238
That is, you can create a branch in your switch statement that is used
227239
whenever the input value is contained in a range. These range
228240
expressions are created with the operator `...`. Is important
229241
to emphasize that the ranges created by this operator are
230242
inclusive on both ends.
231243

232-
For example, I could easily change the code example above to support all
244+
For example, I could easily change the previous code example to support all
233245
levels between 0 and 100. Like this:
234246

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

254266

267+
#### Labeled switch statements
268+
269+
At @sec-blocks we have talked about labeling blocks, and also, about using these labels
270+
to return a value from the block. Well, from version 0.14.0 and onwards of the `zig` compiler,
271+
you can also apply labels over switch statements,
272+
which makes possible to implement almost a "C goto like" pattern in Zig.
273+
274+
For example, if you give the label `xsw` to a switch statement, you can use this
275+
label in conjunction with the `continue` keyword to go back to the beginning of the switch
276+
statement. In the example below, the execution goes back to the beginning of the
277+
switch statement two times, before ending at the `3` branch.
278+
279+
```{zig}
280+
#| auto_main: false
281+
#| build_type: "lib"
282+
#| eval: false
283+
xsw: switch (@as(u8, 1)) {
284+
1 => continue :xsw 2,
285+
2 => continue :xsw 3,
286+
3 => return,
287+
4 => {},
288+
}
289+
```
290+
255291

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

ZigExamples/base64/base64_basic.zig

+11-13
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,11 @@ const Base64 = struct {
3939
if (input.len == 0)
4040
return "";
4141

42-
const n_output = _calc_encode_length(input);
42+
const n_output = try _calc_encode_length(input);
4343
var output = try allocator.alloc(u8, n_output);
4444
var tmp_buffer = [3]u8{ 0, 0, 0 };
4545
var count: u8 = 0;
46-
var output_index: u64 = 0;
46+
var output_index: usize = 0;
4747

4848
for (input, 0..) |_, i| {
4949
tmp_buffer[count] = input[i];
@@ -80,7 +80,7 @@ const Base64 = struct {
8080
if (input.len == 0)
8181
return "";
8282

83-
const n_output = _calc_decode_length(input);
83+
const n_output = try _calc_decode_length(input);
8484
var tmp_buffer = [4]u8{ 0, 0, 0, 0 };
8585
var output = try allocator.alloc(u8, n_output);
8686
var count: u8 = 0;
@@ -109,25 +109,23 @@ const Base64 = struct {
109109
}
110110
};
111111

112-
fn _calc_encode_length(input: []const u8) u64 {
113-
const len_as_float: f64 = @floatFromInt(input.len);
112+
fn _calc_encode_length(input: []const u8) !usize {
114113
if (input.len < 3) {
115-
const n_output: u64 = 4;
114+
const n_output: usize = 4;
116115
return n_output;
117116
}
118117

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

123-
fn _calc_decode_length(input: []const u8) u64 {
124-
const len_as_float: f64 = @floatFromInt(input.len);
122+
fn _calc_decode_length(input: []const u8) !usize {
125123
if (input.len < 4) {
126-
const n_output: u64 = 3;
124+
const n_output: usize = 3;
127125
return n_output;
128126
}
129-
const n_output: u64 = @intFromFloat(@floor(len_as_float / 4.0) * 3.0);
130-
return n_output;
127+
const n_output: usize = try std.math.divFloor(usize, input.len, 4);
128+
return n_output * 3;
131129
}
132130

133131
pub fn main() !void {

_freeze/Chapters/01-base64/execute-results/html.json

+2-2
Large diffs are not rendered by default.

_freeze/Chapters/03-structs/execute-results/html.json

+2-2
Large diffs are not rendered by default.

_freeze/index/execute-results/html.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
2-
"hash": "59aac007bbff258bb5af0e77915366c8",
2+
"hash": "87da007e8766ae15b718d8b3223b480f",
33
"result": {
44
"engine": "knitr",
5-
"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:[email protected])\n\nPersonal website: <https://pedro-faria.netlify.app/>\n",
5+
"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:[email protected])\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",
66
"supporting": [],
77
"filters": [
88
"rmarkdown/pagebreak.lua"

contributors.txt

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1-
name,user_name,
2-
Calin Martinconi,@martinconic,
1+
name,user_name
2+
Calin Martinconi,@martinconic
3+
Steffen Roller,@sroller
4+
Chris Boesch,@chrboesch
5+
Lv Sihan,@Pokryton

0 commit comments

Comments
 (0)