<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Niclas</title>
    <description>The latest articles on DEV Community by Niclas (@nidomiro).</description>
    <link>https://dev.to/nidomiro</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F684862%2Fd6d33f8b-41a1-4ba4-87ea-2cb29935bf39.jpeg</url>
      <title>DEV Community: Niclas</title>
      <link>https://dev.to/nidomiro</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nidomiro"/>
    <language>en</language>
    <item>
      <title>Luxon Timezones and JS-Date interop</title>
      <dc:creator>Niclas</dc:creator>
      <pubDate>Wed, 23 Nov 2022 16:00:20 +0000</pubDate>
      <link>https://dev.to/nidomiro/luxon-timezones-and-js-date-interop-5ceg</link>
      <guid>https://dev.to/nidomiro/luxon-timezones-and-js-date-interop-5ceg</guid>
      <description>&lt;p&gt;If you ever wondered how &lt;a href="https://moment.github.io/luxon/" rel="noopener noreferrer"&gt;luxon&lt;/a&gt; and native &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date?retiredLocale=de" rel="noopener noreferrer"&gt;JS-Dates&lt;/a&gt; (with TimeZones) behave when converting them between each other and &lt;a href="https://www.w3.org/TR/NOTE-datetime" rel="noopener noreferrer"&gt;ISO-Date-Strings&lt;/a&gt; here are my tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;luxon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTimezoneOffset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TimeZoneOffset(min): &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TimeZoneOffset( h ): &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cm"&gt;/*
TimeZoneOffset(min):  60
TimeZoneOffset( h ):  1
 */&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;strLocal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2023-07-21T09:35:31.825+01:00&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;strUtc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2023-07-21T08:35:31.825Z&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jsDateLocal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;strLocal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jsDateUTC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;strUtc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dateTimeLocal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromISO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;strLocal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dateTimeUTC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromISO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;strUtc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`ToLocal`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;jsDateLocal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jsDateLocal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;jsDateUTC&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jsDateUTC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;dateTimeLocal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dateTimeLocal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;dateTimeUTC&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dateTimeUTC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;dateTimeLocalFull&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dateTimeLocal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DATETIME_FULL&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;dateTimeUTCFull&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dateTimeUTC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DATETIME_FULL&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="cm"&gt;/*
┌───────────────────┬───────────────────────────────────┐
│      (index)      │              Values               │
├───────────────────┼───────────────────────────────────┤
│    jsDateLocal    │     '7/21/2023, 10:35:31 AM'      │
│     jsDateUTC     │     '7/21/2023, 10:35:31 AM'      │
│   dateTimeLocal   │            '7/21/2023'            │
│    dateTimeUTC    │            '7/21/2023'            │
│ dateTimeLocalFull │ 'July 21, 2023 at 10:35 AM GMT+2' │
│  dateTimeUTCFull  │ 'July 21, 2023 at 10:35 AM GMT+2' │
└───────────────────┴───────────────────────────────────┘
 */&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`ToIsoTimestamp`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;jsDateLocalToIso&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jsDateLocal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;jsDateUTCToIso&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jsDateUTC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;

  &lt;span class="na"&gt;dateTimeLocalToIso&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dateTimeLocal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toISO&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;dateTimeUtcToIso&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dateTimeUTC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toISO&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;

  &lt;span class="na"&gt;dateTimeLocalToUtcToIso&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dateTimeLocal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUTC&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISO&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;dateTimeUtcToUtcToIso&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dateTimeUTC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUTC&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISO&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="cm"&gt;/*
┌─────────────────────────┬─────────────────────────────────┐
│         (index)         │             Values              │
├─────────────────────────┼─────────────────────────────────┤
│    jsDateLocalToIso     │   '2023-07-21T08:35:31.825Z'    │
│     jsDateUTCToIso      │   '2023-07-21T08:35:31.825Z'    │
│   dateTimeLocalToIso    │ '2023-07-21T10:35:31.825+02:00' │
│    dateTimeUtcToIso     │ '2023-07-21T10:35:31.825+02:00' │
│ dateTimeLocalToUtcToIso │   '2023-07-21T08:35:31.825Z'    │
│  dateTimeUtcToUtcToIso  │   '2023-07-21T08:35:31.825Z'    │
└─────────────────────────┴─────────────────────────────────┘
 */&lt;/span&gt;


&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`jsDate to DateTime to Iso`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;fromJsLocal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromJSDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsDateLocal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toISO&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;fromJsUTC&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromJSDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsDateUTC&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toISO&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;

  &lt;span class="na"&gt;fromJsLocalWithUtc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromJSDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsDateLocal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;toISO&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;fromJsUTCWithUtc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromJSDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsDateUTC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;toISO&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;

  &lt;span class="na"&gt;fromJsLocalToUtc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromJSDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsDateLocal&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toUTC&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISO&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;fromJsUTCToUtc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromJSDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsDateUTC&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toUTC&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISO&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;

  &lt;span class="na"&gt;fromJsLocalWithEuropeBerlin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromJSDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsDateLocal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Europe/Berlin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;toISO&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;fromJsUTCWithEuropeBerlin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromJSDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsDateUTC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Europe/Berlin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;toISO&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;

  &lt;span class="na"&gt;fromJsLocalWithEuropeBerlinToUtc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromJSDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsDateLocal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Europe/Berlin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;toUTC&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISO&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;fromJsUTCWithEuropeBerlinToUtc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromJSDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsDateUTC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Europe/Berlin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;toUTC&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISO&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="cm"&gt;/*
┌──────────────────────────────────┬─────────────────────────────────┐
│             (index)              │             Values              │
├──────────────────────────────────┼─────────────────────────────────┤
│           fromJsLocal            │ '2023-07-21T10:35:31.825+02:00' │
│            fromJsUTC             │ '2023-07-21T10:35:31.825+02:00' │
│        fromJsLocalWithUtc        │   '2023-07-21T08:35:31.825Z'    │
│         fromJsUTCWithUtc         │   '2023-07-21T08:35:31.825Z'    │
│         fromJsLocalToUtc         │   '2023-07-21T08:35:31.825Z'    │
│          fromJsUTCToUtc          │   '2023-07-21T08:35:31.825Z'    │
│   fromJsLocalWithEuropeBerlin    │ '2023-07-21T10:35:31.825+02:00' │
│    fromJsUTCWithEuropeBerlin     │ '2023-07-21T10:35:31.825+02:00' │
│ fromJsLocalWithEuropeBerlinToUtc │   '2023-07-21T08:35:31.825Z'    │
│  fromJsUTCWithEuropeBerlinToUtc  │   '2023-07-21T08:35:31.825Z'    │
└──────────────────────────────────┴─────────────────────────────────┘
 */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>http</category>
    </item>
    <item>
      <title>Using ts-node in nx-monorepos</title>
      <dc:creator>Niclas</dc:creator>
      <pubDate>Tue, 22 Nov 2022 19:10:10 +0000</pubDate>
      <link>https://dev.to/nidomiro/using-ts-node-in-nx-monorepos-2omg</link>
      <guid>https://dev.to/nidomiro/using-ts-node-in-nx-monorepos-2omg</guid>
      <description>&lt;p&gt;At my current work we use monorepos a lot. We use &lt;a href="https://nx.dev/"&gt;nx&lt;/a&gt; as tool to manage the different projects in the repo.&lt;br&gt;
Naturally you also need some scripts to automate some tasks in the repository. Sometimes you also want to use libraries of your monorepo inside these scripts.&lt;/p&gt;

&lt;p&gt;To be able to do that you just need to install &lt;a href="https://www.npmjs.com/package/tsconfig-paths"&gt;tsconfig-paths&lt;/a&gt; (&lt;code&gt;npm install -D tsconfig-paths&lt;/code&gt;) and alter the &lt;code&gt;ts-config&lt;/code&gt; file you use for &lt;a href="https://www.npmjs.com/package/ts-node"&gt;ts-node&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./tsconfig.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="nl"&gt;"ts-node"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;It&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;faster&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;skip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;typechecking.&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Remove&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;want&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ts-node&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;typechecking.&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"transpileOnly"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nl"&gt;"files"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nl"&gt;"require"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"tsconfig-paths/register"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;compilerOptions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;specified&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;here&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;will&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;override&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;those&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;declared&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;below&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;but&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;*only*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ts-node.&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;Useful&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;want&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ts-node&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;tsc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;use&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;different&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;options&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;single&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;tsconfig.json.&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key part is the &lt;code&gt;"require": ["tsconfig-paths/register"]&lt;/code&gt; as it enables ts-node to resolve the path of your libraries.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>productivity</category>
      <category>node</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Using Ory Keto to secure NestJS backends</title>
      <dc:creator>Niclas</dc:creator>
      <pubDate>Sun, 13 Nov 2022 13:10:27 +0000</pubDate>
      <link>https://dev.to/nidomiro/using-ory-keto-to-secure-nestjs-backends-5gbg</link>
      <guid>https://dev.to/nidomiro/using-ory-keto-to-secure-nestjs-backends-5gbg</guid>
      <description>&lt;p&gt;&lt;a href="https://www.ory.sh/docs/keto/"&gt;Ory Keto&lt;/a&gt; is a Permissions &amp;amp; Access Control System based on &lt;a href="https://research.google/pubs/pub48190/"&gt;Zanzibar: Google’s Consistent, Global Authorization System&lt;/a&gt;.&lt;br&gt;
It uses a graph to evaluate permissions and is therefore very flexible in its structure.&lt;br&gt;
Allowed access is nothing more than an existing path in the graph.&lt;/p&gt;

&lt;p&gt;For checking permissions it uses a structure called Relation Tuple.&lt;br&gt;
The string-representation has the following syntax &lt;a href="https://en.wikipedia.org/wiki/Backus%E2%80%93Naur_form"&gt;(BNF)&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;relation-tuple&amp;gt; ::= &amp;lt;object&amp;gt;'#'relation'@'&amp;lt;subject&amp;gt;
&amp;lt;object&amp;gt; ::= namespace':'object_id
&amp;lt;subject&amp;gt; ::= subject_id | &amp;lt;subject_set&amp;gt;
&amp;lt;subject_set&amp;gt; ::= &amp;lt;object&amp;gt;'#'relation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A valid example would be &lt;code&gt;namespace:object#relation@subjectId&lt;/code&gt; or &lt;code&gt;namespace:object#relation@subjectNamespace:subjectObject#subjectRelation&lt;/code&gt;.&lt;br&gt;
The latter can be difficult to read, therefore you'll often see the following variant: &lt;code&gt;namespace:object#relation@(subjectNamespace:subjectObject#subjectRelation)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Relation Tuples can be verbalized.&lt;br&gt;
The Relation Tuple &lt;code&gt;sharedFiles:a.txt#access@dirs:b#access&lt;/code&gt; can be verbalized as "Anyone with &lt;code&gt;access&lt;/code&gt; to &lt;code&gt;dirs:b&lt;/code&gt; has &lt;code&gt;access&lt;/code&gt; to &lt;code&gt;sharedFiles:a.txt&lt;/code&gt;".&lt;/p&gt;

&lt;p&gt;The SDKs of Ory Keto (REST and gRPC) use an object/class representation of the Relation Tuple. This is fine for most cases but not as convenient to use and understand as a simple string.&lt;/p&gt;

&lt;p&gt;Because of this I wrote a small Typescript library to parse the string-representation of a Relation Tuple into the needed object-representation.&lt;/p&gt;

&lt;p&gt;The general variant, not tied to Keto, is called &lt;code&gt;@nidomiro/relation-tuple-parser&lt;/code&gt; (&lt;a href="https://www.npmjs.com/package/@nidomiro/relation-tuple-parser"&gt;npm&lt;/a&gt;, &lt;a href="https://github.com/nidomiro/relation-tuple-parser/tree/main/packages/typescript"&gt;github&lt;/a&gt;).&lt;br&gt;
It supports converting static strings and strings with placeholders.&lt;br&gt;
The latter is especially useful if you want to substitute e.g. the id of the currently logged-in user in the Relation Tuple.&lt;/p&gt;

&lt;p&gt;The variant for Keto &lt;code&gt;@nidomiro/relation-tuple-parser-ory-keto&lt;/code&gt; (&lt;a href="https://www.npmjs.com/package/@nidomiro/relation-tuple-parser-ory-keto"&gt;npm&lt;/a&gt;, &lt;a href="https://github.com/nidomiro/relation-tuple-parser/tree/main/packages/typescript-ory-keto"&gt;GitHub&lt;/a&gt;) just contains converters. They convert the given Relation Tuple (with, or without replacements) into a form you can use with the Keto SDK.&lt;/p&gt;

&lt;p&gt;Let's look into a usage-example.&lt;/p&gt;
&lt;h2&gt;
  
  
  Example with &lt;a href="https://nestjs.com/"&gt;NestJS&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I assume you already know NestJS and are in a freshly created project. Additionally, I assume that Keto is already accessible.&lt;/p&gt;

&lt;p&gt;The full source-code of this example can be found &lt;a href="https://github.com/nidomiro/relation-tuple-parser/tree/main/packages/examples/nestjs-guard"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  What we want to accomplish
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;We want an easy way to secure a backend route with Keto.&lt;/li&gt;
&lt;li&gt;The person developing a new route shouldn't be responsible for communication with Keto.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The routes permissions should therefore be configurable via a Decorator. The choice fell to the following syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;GuardedBy&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;currentUserId&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`groups:users#member@&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;currentUserId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is concise and flexible at the same time.&lt;br&gt;
We can use it, to secure our &lt;code&gt;getData&lt;/code&gt; route:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;AppController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;GuardedBy&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;currentUserId&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`groups:users#member@&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;currentUserId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Access grated!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Implementing the Decorator
&lt;/h3&gt;

&lt;p&gt;How is the decorator shown above implemented?&lt;/p&gt;

&lt;p&gt;In fact, it is relatively simple. It accepts a string or a generator function as parameter. Then it parses the given Relation Tuples and stores them inside the Handlers' metadata.&lt;br&gt;
This way, the parsing happens at app-startup and not with every request.&lt;/p&gt;

&lt;p&gt;The decorator &lt;a href="https://github.com/nidomiro/relation-tuple-parser/blob/main/packages/examples/nestjs-guard/src/app/guard/guarded-by.decorator.ts"&gt;(full source)&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GuardedBy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;relationTuple&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;RelationTupleStringGenerator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PossibleReplacements&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;valueToSet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GuardedByMetadataType&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;relationTuple&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;valueToSet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parseRelationTupleWithReplacements&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;relationTuple&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;unwrapOrThrow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;valueToSet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parseRelationTupleWithReplacements&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;relationTuple&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;unwrapOrThrow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;SetMetadata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;GUARDED_BY_METADATA_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;valueToSet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that both variants are stored as a &lt;code&gt;RelationTupleWithReplacements&lt;/code&gt;. This way we only have to think about one variant during the evaluation.&lt;/p&gt;

&lt;p&gt;To statically type the possible replacements we create a type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PossibleReplacements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;currentUserId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unauthorized&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Implementing the (App-) Guard
&lt;/h3&gt;

&lt;p&gt;The actual check of the Relation Tuple against Keto happens inside the Guard - &lt;code&gt;KetoGuard&lt;/code&gt; &lt;a href="https://github.com/nidomiro/relation-tuple-parser/blob/main/packages/examples/nestjs-guard/src/app/guard/keto-guard.ts"&gt;(full source)&lt;/a&gt; in our case.&lt;/p&gt;

&lt;p&gt;First we need to add the Keto SDK: &lt;code&gt;npm i @ory/keto-grpc-client&lt;/code&gt; and if you need the REST-client &lt;code&gt;npm i @ory/keto-client&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We use the gRPC variant for checking, because it is a bit faster than the HTTP variant - at least in theory.&lt;/p&gt;

&lt;p&gt;What we need to do in the Guard:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;get the value set by the Guard (the &lt;code&gt;RelationTupleWithReplacements&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;get the needed replacement values. In our case just &lt;code&gt;currentUserId&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;replace the values in the &lt;code&gt;RelationTuple&lt;/code&gt; and evaluate the tuple against Keto&lt;/li&gt;
&lt;li&gt;Allow / Deny access according to the result of the check.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For step 1 create another method inside &lt;code&gt;guarded-by.decorator.ts&lt;/code&gt; &lt;a href="https://github.com/nidomiro/relation-tuple-parser/blob/17a49ee97bc5075dfef67b94a13bc7f014f4dfd9/packages/examples/nestjs-guard/src/app/guard/guarded-by.decorator.ts#L25"&gt;(full source)&lt;/a&gt; with the following definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getGuardingRelationTuple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;reflector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Reflector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Parameters&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Reflector&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;get&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;RelationTupleWithReplacements&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PossibleReplacements&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;reflector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;GuardedByMetadataType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;GUARDED_BY_METADATA_KEY&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;GUARDED_BY_METADATA_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can retrieve the &lt;code&gt;RelationTupleWithReplacements&lt;/code&gt; if any is set. Otherwise, we get null instead.&lt;/p&gt;

&lt;p&gt;For step 2 I chose the "simple demo approach" and just extract a &lt;code&gt;userId&lt;/code&gt; from the URL parameters. &lt;strong&gt;Only&lt;/strong&gt; use this approach for demos, &lt;strong&gt;never&lt;/strong&gt; for production! &lt;a href="https://github.com/nidomiro/relation-tuple-parser/blob/main/packages/examples/nestjs-guard/src/app/guard/keto-guard.ts#L50"&gt;(source code)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 3 is implemented in &lt;code&gt;keto-read-client.service.ts&lt;/code&gt; &lt;a href="https://github.com/nidomiro/relation-tuple-parser/blob/main/packages/examples/nestjs-guard/src/app/keto-read-client.service.ts#L19"&gt;(full source)&lt;/a&gt;.&lt;br&gt;
With &lt;code&gt;RelationTupleWithReplacementsConverter.toKetoGrpcCheckRequest&lt;/code&gt; we replace the values inside the RelationTuple and store the result directly in an &lt;code&gt;CheckRequest&lt;/code&gt;, needed by Keto's gRPC client.&lt;br&gt;
The next step is to call the Keto client with our &lt;code&gt;CheckRequest&lt;/code&gt; and return the result. Note that the error-status &lt;code&gt;NOT_FOUND&lt;/code&gt; is handled as "not allowed" &lt;a href="https://github.com/nidomiro/relation-tuple-parser/blob/main/packages/examples/nestjs-guard/src/app/keto-read-client.service.ts#L29"&gt;(see here)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The last and final step is to use the Result and allow or deny the Request.&lt;/p&gt;

&lt;p&gt;Now we need to load some rules into keto and check the result.&lt;br&gt;
For this demo the necessary rules are set in keto during app-startup &lt;a href="https://github.com/nidomiro/relation-tuple-parser/blob/main/packages/examples/nestjs-guard/src/main.ts#L13"&gt;(full-source)&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;initKeto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ketoWriteService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;KetoWriteClientService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ketoWriteService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addRelationTuple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parseRelationTuple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;groups:users#member@user1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;unwrapOrThrow&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ketoWriteService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addRelationTuple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parseRelationTuple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;groups:users#member@user2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;unwrapOrThrow&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these Relation Tuples set, you can now check the result yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allowed access: &lt;a href="http://localhost:3333/api?userId=user1"&gt;http://localhost:3333/api?userId=user1&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Allowed access: &lt;a href="http://localhost:3333/api?userId=user2"&gt;http://localhost:3333/api?userId=user2&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Forbidden access: &lt;a href="http://localhost:3333/api?userId=user3"&gt;http://localhost:3333/api?userId=user3&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Forbidden access: &lt;a href="http://localhost:3333/api"&gt;http://localhost:3333/api&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Allowed Access returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Access grated!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Denied Access returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"statusCode":403,"message":"Forbidden resource","error":"Forbidden"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it. Now you can add more Controller and/or Handler and just use the &lt;code&gt;@GuardedBy&lt;/code&gt; decorator to secure them.&lt;/p&gt;

&lt;p&gt;In a real world-example you would also validate the session and fetch the data of the &lt;code&gt;currentUserId&lt;/code&gt; inside the guard. The fetched data can then be attached to the request and therefore be used by the Handler without the need to fetch the data again.&lt;/p&gt;

&lt;p&gt;If you have any questions or improvements feel free to comment below.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>webdev</category>
      <category>security</category>
    </item>
    <item>
      <title>Using OSS to secure your web-app / app / ...</title>
      <dc:creator>Niclas</dc:creator>
      <pubDate>Fri, 11 Nov 2022 08:22:48 +0000</pubDate>
      <link>https://dev.to/nidomiro/using-oss-to-secure-your-web-app-app--bmp</link>
      <guid>https://dev.to/nidomiro/using-oss-to-secure-your-web-app-app--bmp</guid>
      <description>&lt;p&gt;"Security is hard. You shouldn't implement it yourself.".&lt;/p&gt;

&lt;p&gt;That's a phrase I heard a lot by now, and it's true for the most part.&lt;br&gt;
Aside from that why bother with implementing the same functionality for different projects all over again.&lt;/p&gt;

&lt;p&gt;To solve this issue often providers like &lt;a href="https://firebase.google.com/"&gt;Firebase&lt;/a&gt;, &lt;a href="https://auth0.com"&gt;Auth0&lt;/a&gt;, ... step in an provide user-management and permission-management.&lt;br&gt;
These solutions work fine but get costly very quickly.&lt;br&gt;
But the main 'not-selling point' for me is that they are not opensource and cannot be hosted by myself.&lt;br&gt;
I like being able to have control over things I invest my time in.&lt;/p&gt;

&lt;p&gt;There are some opensource solutions that are trying to solve this issue; one of them is &lt;a href="https://www.keycloak.org/"&gt;Keycloak&lt;/a&gt;.&lt;br&gt;
&lt;a href="https://www.keycloak.org/"&gt;Keycloak&lt;/a&gt; solves this problem well but introduces some other problems: It is very complex and custom styling is everything but easy if you want to use something like &lt;a href="https://nextjs.org/"&gt;Next.js&lt;/a&gt; to fully integrate the Login/Registration into your webapp.&lt;/p&gt;

&lt;p&gt;But Keycloak isn't the only player in the field.&lt;/p&gt;

&lt;p&gt;After some searching I found &lt;a href="https://www.ory.sh/"&gt;Ory&lt;/a&gt;.&lt;br&gt;
They provide several isolated applications for different auth concerns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.ory.sh/docs/kratos"&gt;Ory Kratos&lt;/a&gt; for Identity Management&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.ory.sh/docs/keto"&gt;Ory Keto&lt;/a&gt; for Permissions &amp;amp; Access Control based on &lt;a href="https://research.google/pubs/pub48190/"&gt;Zanzibar: Google’s Consistent, Global Authorization System&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.ory.sh/docs/hydra"&gt;Ory Hydra&lt;/a&gt; for providing OAuth2 and OpenID Connect functionality&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can use everything together in their cloud variant 'Ory Network' or host it yourself. It is even possible to use only some applications, as any can be used without the others.&lt;/p&gt;

&lt;p&gt;The functionality needed for 90% of all applications can be covered by Kratos and Keto; yes even &lt;a href="https://www.ory.sh/docs/kratos/social-signin/overview"&gt;Social sign-in&lt;/a&gt;, &lt;a href="https://www.ory.sh/docs/kratos/mfa/overview"&gt;Multi-factor Authentication&lt;/a&gt; and &lt;a href="https://www.ory.sh/docs/kratos/passwordless/webauthn"&gt;Passwordless via WebAuthn&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What sets Ory's products apart from other opensource solutions is that their mantra is 'Bring your own UI'.&lt;br&gt;
The (self-hosted) applications itself only provide an API (REST and partially gRPC).&lt;br&gt;
You can use one of the (example-) UI's developed by Ory, but the normal way is to use your own UI.&lt;br&gt;
More areas where Ory is different can be found in the &lt;a href="https://www.ory.sh/docs/welcome#why-ory-is-different"&gt;docs or Ory&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The project I'm currently working on uses Next.js; and it's &lt;a href="https://www.ory.sh/nextjs/"&gt;directly supported by Ory&lt;/a&gt;. It works flawless so far.&lt;/p&gt;

&lt;p&gt;If you decide to use Kratos it can seem odd at first, but the design-decisions make sense if you think about them.&lt;br&gt;
Kratos will provide an abstract representation of what elements are needed e.g. on the login-page / registration / user-settings.&lt;br&gt;
With this abstract representation it is possible to render HTML-Elements or an App-UI dynamically.&lt;br&gt;
The benefit of this technique: Adding e.g. a new Social-login is as easy as adding it in the Kratos config. Your UI will update automatically - without any code change or deployment.&lt;/p&gt;

&lt;p&gt;You can use Kratos to store much more than just email and password.&lt;br&gt;
With custom &lt;a href="https://www.ory.sh/docs/kratos/manage-identities/customize-identity-schema"&gt;Identity Schemas&lt;/a&gt; you can define which fields are needed or possible for an Identity (= User).&lt;br&gt;
There can even be different types of Identities, therefore requiring different information, at the same time.&lt;/p&gt;

&lt;p&gt;For handling permissions and access-control Ory Keto can be used.&lt;br&gt;
It is based on &lt;a href="https://research.google/pubs/pub48190/"&gt;Zanzibar: Google’s Consistent, Global Authorization System&lt;/a&gt; and uses a graph to evaluate permissions.&lt;br&gt;
Through this method it is very flexible in the permissions are organized.&lt;br&gt;
Allowed access is represented as an existing path between two nodes in the graph.&lt;/p&gt;

&lt;p&gt;Hierarchical structures can easily be realized and changed at any time.&lt;br&gt;
With the right concept it is even possible to redo your entire permission-structure without the need to deploy your application again.&lt;/p&gt;

&lt;p&gt;Maybe it's worth trying out Ory for your next project, you probably will like it ;)&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>webdev</category>
      <category>security</category>
    </item>
    <item>
      <title>Rust-04: More operators and loops</title>
      <dc:creator>Niclas</dc:creator>
      <pubDate>Wed, 09 Nov 2022 11:00:00 +0000</pubDate>
      <link>https://dev.to/nidomiro/rust-04-more-operators-and-loops-3g21</link>
      <guid>https://dev.to/nidomiro/rust-04-more-operators-and-loops-3g21</guid>
      <description>&lt;p&gt;In the last post we improved the simple program to be extendable with other operators.&lt;br&gt;
In this post we will implement more operators and a loop.&lt;/p&gt;

&lt;p&gt;Let's start with the simple task: adding more operators.&lt;br&gt;
To support more operators we have to change two parts of the calculator, the parsing and the evaluation.&lt;br&gt;
First let's look into changing the parser.&lt;br&gt;
For this we simply add the new operators (&lt;code&gt;-*/&lt;/code&gt;) to the regex inside &lt;code&gt;Operation::from_string&lt;/code&gt;.&lt;br&gt;
The resulting regex will look like this: &lt;code&gt;^\s*(\d+)\s*([+\-*/])\s*(\d+)\s*$&lt;/code&gt;.&lt;br&gt;
Now the parser accepts the new operators; first part done.&lt;/p&gt;

&lt;p&gt;The second part to change is the evaluation of the parsed operation.&lt;br&gt;
Adding the new operators is as simple as adding more arms to &lt;code&gt;match&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Operation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sc"&gt;'+'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;Operation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sc"&gt;'-'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;Operation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sc"&gt;'*'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;Operation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sc"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{} is not a valid operator"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="py"&gt;.operator&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the current state, the app can now accept &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt;, &lt;code&gt;/&lt;/code&gt; as operators and calculate the result.&lt;/p&gt;

&lt;p&gt;Since we expanded the capabilities, we can also look for some possible refactorings.&lt;br&gt;
You might see, that the execution of the &lt;code&gt;Operation&lt;/code&gt; still happens inside the main function.&lt;br&gt;
It would be cleaner to move the evaluation closer to &lt;code&gt;Operation&lt;/code&gt; itself.&lt;br&gt;
So let's add another function to &lt;code&gt;impl Operation&lt;/code&gt; called &lt;code&gt;execute&lt;/code&gt; and move the mentioned code to that function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Operation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// &amp;lt;snip&amp;gt;&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Operation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sc"&gt;'+'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;Operation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sc"&gt;'-'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;Operation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sc"&gt;'*'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;Operation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sc"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{} is not a valid operator"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="py"&gt;.operator&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Right now &lt;code&gt;execute&lt;/code&gt; only returns a &lt;code&gt;String&lt;/code&gt; in case of an error.&lt;br&gt;
To be more specific, what error occurred we add another struct to represent this error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;InvalidOperatorError&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;char&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// &amp;lt;snip&amp;gt;&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Operation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// &amp;lt;snip&amp;gt;&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;InvalidOperatorError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Operation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sc"&gt;'+'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;Operation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sc"&gt;'-'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;Operation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sc"&gt;'*'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;Operation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sc"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;InvalidOperatorError&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="py"&gt;.operator&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After these changes, we are at state: &lt;a href="https://github.com/nidomiro/learning-rust-calculator/tree/2d6c605ac172308c7f06ec19a965c61cb12f3459"&gt;2d6c605a&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Until now, we have completed task one: implementing more possible operators.&lt;br&gt;
The second task is to change the calculator to accept multiple calculations one after the other.&lt;br&gt;
A loop is a prime example to achieve this behaviour.&lt;/p&gt;

&lt;p&gt;Just wrapping everything in a loop does enable multiple calculations, but the user of our calculator has no way of exiting the program.&lt;br&gt;
We want to be able to type 'quit' to exit the program.&lt;br&gt;
The code below will achieve just that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Please enter a calculation (or quit to exit)"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.read_line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Could not read line"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="nf"&gt;.trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"quit"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"exiting..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Operation&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Your input is invalid"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="nf"&gt;.execute&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The result is: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But we have another problem to fix.&lt;/p&gt;

&lt;p&gt;Since we allow multiple calculations we don't want the calculator to crash on an invalid input anymore.&lt;br&gt;
Using &lt;code&gt;expect&lt;/code&gt; and &lt;code&gt;unwrap&lt;/code&gt; as error-handlers, will result in a crash of the app if they encounter an error-state;&lt;br&gt;
so we need to exchange them.&lt;br&gt;
Obviously we use &lt;code&gt;match&lt;/code&gt; instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Please enter a calculation (or quit to exit)"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.read_line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Could not read line"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="nf"&gt;.trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"quit"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"exiting..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="nn"&gt;Operation&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nb"&gt;None&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Your input was invalid"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="nf"&gt;.execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;InvalidOperatorError&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The operator {} is invalid"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;


        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The result is: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we get an info, if the input is invalid and can try again on the next iteration.&lt;/p&gt;

&lt;p&gt;After all changes of this post, we are at state: &lt;a href="https://github.com/nidomiro/learning-rust-calculator/tree/8322be09454ab3e77a77e9984a1d3c5638d26b2d"&gt;8322be09&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the next post we will change the structure radically to be able to support multiple operators in one input - at least on the execution side.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>programming</category>
    </item>
    <item>
      <title>Rust-03: Improving the simple program</title>
      <dc:creator>Niclas</dc:creator>
      <pubDate>Tue, 08 Nov 2022 11:00:00 +0000</pubDate>
      <link>https://dev.to/nidomiro/rust-03-improving-the-simple-program-jdf</link>
      <guid>https://dev.to/nidomiro/rust-03-improving-the-simple-program-jdf</guid>
      <description>&lt;p&gt;In the last post we created a simple program that would accept an input like &lt;code&gt;5+5&lt;/code&gt; and calculates the result.&lt;br&gt;
In this post we will improve this program.&lt;/p&gt;

&lt;p&gt;To prepare for adding more operators we need to improve the input-parsing.&lt;br&gt;
Currently, we just split the input-string at the plus-sign.&lt;br&gt;
If we want to know the operator, we have to choose another approach.&lt;/p&gt;

&lt;p&gt;In this case I chose regex:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[derive(Debug)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Operation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Operation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;from_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Operation&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;regex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Regex&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;r"^\s*(\d+)\s*([+])\s*(\d+)\s*$"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;regex&lt;/span&gt;&lt;span class="nf"&gt;.captures&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Operation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="nf"&gt;.parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="nf"&gt;.parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="nf"&gt;.parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see we have a new thing called &lt;code&gt;struct&lt;/code&gt; in the code.&lt;br&gt;
If you are coming from a language like Java or Typescript, a struct can be seen as a class without any methods.&lt;br&gt;
This struct is called &lt;code&gt;Operation&lt;/code&gt; and as the name suggests it holds an operation.&lt;br&gt;
The fields &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt; are both typed as an &lt;code&gt;i32&lt;/code&gt; or in other words a "signed 32-bit integer".&lt;br&gt;
The field &lt;code&gt;operator&lt;/code&gt; is a &lt;code&gt;char&lt;/code&gt; since we only use one character for an operator.&lt;br&gt;
In rust &lt;code&gt;strings&lt;/code&gt; and &lt;code&gt;chars&lt;/code&gt; are utf-8, therefore a &lt;code&gt;char&lt;/code&gt; can contain one unicode codepoint, not just a byte.&lt;/p&gt;

&lt;p&gt;The other new thing is a &lt;code&gt;impl&lt;/code&gt; called &lt;code&gt;Operation&lt;/code&gt;.&lt;br&gt;
An &lt;code&gt;impl&lt;/code&gt; is the method-part equivalent of a class.&lt;br&gt;
Here you can define methods, that are available to call on the struct with the same name.&lt;br&gt;
In this case we have one method called &lt;code&gt;from_string&lt;/code&gt;.&lt;br&gt;
This method is our new parser.&lt;br&gt;
It takes a string as an input and returns an &lt;code&gt;Operation&lt;/code&gt; wrapped by an &lt;code&gt;Option&lt;/code&gt;.&lt;br&gt;
Rust does not have &lt;code&gt;null&lt;/code&gt;, so every time when there is the possibility that a value could be non-existent an &lt;code&gt;Option&lt;/code&gt; is used.&lt;/p&gt;

&lt;p&gt;If you read the code carefully, you may have noticed that the last statement of the function does not have a semicolon.&lt;br&gt;
That is on purpose.&lt;br&gt;
If the last statement of a function has a semicolon, it returns &lt;code&gt;()&lt;/code&gt; (equivalent to &lt;code&gt;void&lt;/code&gt;), if it isn't preceded by the keyword &lt;code&gt;return&lt;/code&gt;.&lt;br&gt;
You can omit the keyword &lt;code&gt;return&lt;/code&gt; by omitting the semicolon on the last statement of a function.&lt;br&gt;
Then, the value of the last statement is used as the return value.&lt;/p&gt;

&lt;p&gt;Now we have a new method of parsing, so lets look at the new evaluator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Operation&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Your input is invalid"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Operation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sc"&gt;'+'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{} is not a valid operator"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="py"&gt;.operator&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The result is: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we can see another example of a powerful feature of Rust: Pattern matching.&lt;br&gt;
With pattern matching, we can save a lot of else-if-statements.&lt;br&gt;
In this simple case it wouldn't make a big difference, but we want to expand the code.&lt;/p&gt;

&lt;p&gt;So what happens inside the &lt;code&gt;match operation {...&lt;/code&gt; statement?&lt;br&gt;
Each line contains a Pattern, followed by &lt;code&gt;=&amp;gt;&lt;/code&gt; and a statement or block.&lt;br&gt;
The pattern &lt;code&gt;Operation { left, operator: '+', right }&lt;/code&gt; matches every &lt;code&gt;Operation&lt;/code&gt; with &lt;code&gt;+&lt;/code&gt; as its operator.&lt;br&gt;
&lt;code&gt;left&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt; have no value assigned in the pattern, so all values match.&lt;br&gt;
You can use &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt; as variables in your following statement, as seen in the code.&lt;br&gt;
&lt;code&gt;x =&amp;gt; ...&lt;/code&gt; matches all cases, it's therefore the &lt;code&gt;default&lt;/code&gt; case.&lt;/p&gt;

&lt;p&gt;After these changes, we are at state: &lt;a href="https://github.com/nidomiro/learning-rust-calculator/tree/24affc713401046fd0c81c11c5beb1e9fe991c6c"&gt;24affc71&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the next post we will add more operators to the calculator and more.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>programming</category>
    </item>
    <item>
      <title>Rust-02: The beginning</title>
      <dc:creator>Niclas</dc:creator>
      <pubDate>Mon, 07 Nov 2022 11:00:00 +0000</pubDate>
      <link>https://dev.to/nidomiro/rust-02-the-beginning-3e9b</link>
      <guid>https://dev.to/nidomiro/rust-02-the-beginning-3e9b</guid>
      <description>&lt;p&gt;At first, I didn't like Rust.&lt;br&gt;
Managing memory myself is something I don't want to do.&lt;br&gt;
After a first look at Rust and setting it aside for a few weeks, it appeared back on my radar.&lt;br&gt;
I thought: "This time I'm looking deeper into it".&lt;br&gt;
So I started by reading the &lt;a href="https://doc.rust-lang.org/book/"&gt;Rust Book&lt;/a&gt;; and I'm still reading it and find new concepts that are really clever.&lt;/p&gt;

&lt;p&gt;One of the first things I discovered is that I do not need to manage memory myself.&lt;br&gt;
The majority of the management will be done by the Rust compiler; I just have to follow some Rules.&lt;br&gt;
These Rules, called "Ownership", are a bit confusing to start with, but make more sense, the more you think about them, and the more you use them.&lt;br&gt;
In combination with the strict differentiation between mutable and immutable structures, you can write code that is easy to read, easy to think about and resource efficient - a combination, I thought never possible.&lt;/p&gt;

&lt;p&gt;It was about chapter 5 when I started my example project - a calculator.&lt;br&gt;
I will use the project in this series to explain some things and concepts.&lt;br&gt;
Keep in mind that this project is just a learning project.&lt;br&gt;
It makes no claim to be perfect, nor very Rust-idiomatic; but it will improve over time and with understanding more concepts.&lt;/p&gt;

&lt;p&gt;You can find the repository here: &lt;a href="https://github.com/nidomiro/learning-rust-calculator"&gt;https://github.com/nidomiro/learning-rust-calculator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I skip the setup process of cargo as it is super simple and well described in the &lt;a href="https://doc.rust-lang.org/book/ch01-03-hello-cargo.html"&gt;Rust-Book&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My first action was to implement a simple addition.&lt;br&gt;
You can enter &lt;code&gt;5+5&lt;/code&gt; and the program outputs &lt;code&gt;10&lt;/code&gt; - hopefully ;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Please enter a calculation"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.read_line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Could not read line"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="nf"&gt;.split&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sc"&gt;'+'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="nf"&gt;.trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Only numbers are allowed"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="nf"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;panic!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Currently only + is a supported operator"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Parts: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{} + {} = {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="py"&gt;.sum&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Source: &lt;a href="https://github.com/nidomiro/learning-rust-calculator/blob/e96ce3c449972be7854545bf0c5d9c386eccbd42/src/main.rs"&gt;https://github.com/nidomiro/learning-rust-calculator/blob/e96ce3c449972be7854545bf0c5d9c386eccbd42/src/main.rs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's examine what happens here.&lt;br&gt;
First we print a text to the console to let the user know what we want from him.&lt;br&gt;
Then we declare a mutable &lt;code&gt;String&lt;/code&gt; instance.&lt;br&gt;
We use this mutable &lt;code&gt;String&lt;/code&gt; and pass a mutable reference to the &lt;code&gt;read_line&lt;/code&gt; method.&lt;br&gt;
When the user enters text and presses Return, the entered text will now be stored in the variable &lt;code&gt;input&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So far so good, but hat does this line &lt;code&gt;.expect("Could not read line")&lt;/code&gt; do?&lt;br&gt;
To understand why this line is there, we have to dive a bit deeper into Rust's error-management.&lt;br&gt;
In general there are two types of errors: recoverable errors and unrecoverable errors.&lt;br&gt;
If you encounter an unrecoverable error, it is not safe to continue executing the program and therefore the program will just exit.&lt;br&gt;
This is called &lt;code&gt;panic&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The other type of errors are recoverable errors.&lt;br&gt;
A recoverable error is represented by the &lt;code&gt;Result&lt;/code&gt; enum.&lt;br&gt;
This enum has two possible values, &lt;code&gt;Ok&lt;/code&gt; if there is no error and &lt;code&gt;Err&lt;/code&gt; if a recoverable error occurred.&lt;br&gt;
This is one of the concepts I learned over the years, and I really like it.&lt;br&gt;
You can see at the method signature what errors can occur and don't need an ugly try-catch block to handle errors (performance is also better).&lt;br&gt;
But what does the line &lt;code&gt;.expect("Could not read line")&lt;/code&gt; now do?&lt;br&gt;
&lt;code&gt;read_line&lt;/code&gt; returns a &lt;code&gt;Result&lt;/code&gt;, and therefore the compiler forces us to handle the error-cases.&lt;br&gt;
&lt;code&gt;.expect("Could not read line")&lt;/code&gt; is a shortcut for "I don't care if errors occur. Just crash the program (panic) with the given message.".&lt;br&gt;
It is obvious that you need to be careful when to use this.&lt;br&gt;
In this case it is ok, because the program is just for learning purposes and not a production program.&lt;/p&gt;

&lt;p&gt;You can read more about error handling in &lt;a href="https://doc.rust-lang.org/book/ch09-00-error-handling.html"&gt;Chapter 09 "Error Handling" of the Rust-Book&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With that out of the way we can continue with the input-processing.&lt;br&gt;
First we split the String at the character '+' and then trim the resulting parts (remove excess whitespace characters) followed by an integer-conversion (&lt;code&gt;.parse()&lt;/code&gt;).&lt;br&gt;
The &lt;code&gt;collect()&lt;/code&gt; is needed, because &lt;code&gt;map&lt;/code&gt; is evaluated lazily and therefore doesn't return a vector itself.&lt;/p&gt;

&lt;p&gt;After checking if we got two numbers in the vector and panicking if not, we print the calculation and its result.&lt;/p&gt;

&lt;p&gt;And there it is, we have our first functioning Rust program :)&lt;/p&gt;

&lt;p&gt;Over the next posts, we will improve the code and add functionality.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>programming</category>
    </item>
    <item>
      <title>Rust-01: Why am I learning Rust?</title>
      <dc:creator>Niclas</dc:creator>
      <pubDate>Sun, 06 Nov 2022 19:36:29 +0000</pubDate>
      <link>https://dev.to/nidomiro/rust-01-why-am-i-learning-rust-433j</link>
      <guid>https://dev.to/nidomiro/rust-01-why-am-i-learning-rust-433j</guid>
      <description>&lt;p&gt;This is a good question, a very good question.&lt;br&gt;
Why am I learning &lt;a href="https://www.rust-lang.org/"&gt;Rust&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;To begin with, I programmed in a lot of languages so far: C++, Python, Swift, Java, Kotlin and TypeScript to name a few.&lt;br&gt;
All languages have some features I missed when programming in other languages.&lt;/p&gt;

&lt;p&gt;Currently, my favorite languages are Kotlin and TypeScript; with Kotlin having the lead.&lt;br&gt;
These languages are expressive, and really nice to write.&lt;br&gt;
I can express my thoughts in code without having to convert them too much in order to make the compiler happy.&lt;/p&gt;

&lt;p&gt;Swift also has some super neat aspects.&lt;br&gt;
For example that you are able to add a &lt;code&gt;potocol&lt;/code&gt; (≃ Interface) to a class after the fact.&lt;br&gt;
This opened my mind to a whole new set of "Metaprogramming"-Methods.&lt;br&gt;
Swift also introduced me to Pattern Matching, a very powerful tool, if used correctly.&lt;br&gt;
Guards are another thing I'm missing from Swift.&lt;br&gt;
Yes you can achieve a similar behaviour in other languages, but having a special keyword for this type of operation helps in code readability.&lt;/p&gt;

&lt;p&gt;Most of my professional programming years I spend programming Java with a short trip to Swift, because a customer wanted to have an iOS app.&lt;br&gt;
During this time Kotlin arrived at my horizon.&lt;br&gt;
It was amazing compared to Java; so concise, so expressive and more secure because the compiler forced you to handle &lt;code&gt;null&lt;/code&gt; values.&lt;br&gt;
Unfortunately the company, I was working for at this time, wasn't as exited as me.&lt;br&gt;
So I used Kotlin for private projects only.&lt;/p&gt;

&lt;p&gt;In 2020, I switched my job and started to use TypeScript as my primary language.&lt;br&gt;
TypeScript added some features which I really liked but also lacked some.&lt;br&gt;
Duck-Typing is very nice, because you don't have to convert your Data-Objects all the time.&lt;br&gt;
This alone is a huge time saver, but at the cost of some strange behaviours.&lt;br&gt;
For example, if you have a class with two attributes you can assign a plain object to a variable with the type of the class, if it has the same attributes (and methods with the same signatures).&lt;br&gt;
This can introduce strange behaviour if you, for example, rely on the type of the class to execute some code, or you rely on code that is executed in the constructor.&lt;br&gt;
I prepared a &lt;a href="https://www.typescriptlang.org/play?#code/FDDGBsEMGdoAgIJwN7DuukBcdoBcAnASwDsBzEDOUAexPwIFdQ8aCAKAShTSo1vo1wAUwB04GmXYAiACI1SZXDQC2wvAAtFcAGaQSoAJ5xScTcLgBhOg2asC0zrz5mt0UZDgBeONJ0FVKxtCOzZpZzgAX2BokBE8TBwkHxJhAHdELjAbITEJKWkAWmLHOPU4ACMk7x4qbF9oVXUtcjgAEyIdHWECYRI8cOiBRpFxSRliwtLswVH89gADSA8cABJkZchIhacZkbzxhYqVuHXjrZ2QYdyxqSWTejx9UGEaHUQ1jYf8Z9f3hG2u2uc0OFW+TwMfw+p2QYNIP0hb0QgJAAHoAFTAADyjDwAAdcVgQPJtI01JptHoDMZTOYgo8mCw2MBJizisBNjh-IFrAzQgRgOccGTmtoOl0en08Bzwb8kQgcCFhILZYj-lzIOBoMrgOjUUA"&gt;code example at typescriptlang.org&lt;/a&gt; to make this point more clear.&lt;/p&gt;

&lt;p&gt;But back to the initial question: Why am I evaluating Rust to become my primary programming language?&lt;/p&gt;

&lt;p&gt;The simple answer is: Rust combines multiple features of languages that I really like.&lt;br&gt;
It is at the same time a low-level (in therms of C and C++) and a high-level (in therms of Kotlin and Typescript) language.&lt;br&gt;
This means I can use it to write webservices and microcontroller / system code.&lt;/p&gt;

&lt;p&gt;Some concepts seem odd at first but absolutely make sense if you think about them more deeply.&lt;br&gt;
In the following articles we'll dive deeper into some of these concepts.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
