<?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: creativcoder</title>
    <description>The latest articles on DEV Community by creativcoder (@creativcoder).</description>
    <link>https://dev.to/creativcoder</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%2F80290%2Fea116670-1ecb-4c9b-a2fb-3741cbc2176d.jpg</url>
      <title>DEV Community: creativcoder</title>
      <link>https://dev.to/creativcoder</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/creativcoder"/>
    <language>en</language>
    <item>
      <title>What is a LSM Tree?</title>
      <dc:creator>creativcoder</dc:creator>
      <pubDate>Fri, 05 Feb 2021 16:45:00 +0000</pubDate>
      <link>https://dev.to/creativcoder/what-is-a-lsm-tree-3d75</link>
      <guid>https://dev.to/creativcoder/what-is-a-lsm-tree-3d75</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhu9c1qfipqucyeytmn8g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhu9c1qfipqucyeytmn8g.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this post, we'll dive deep into Log Structured Merge Tree aka LSM Tree: the data structure underlying many highly scalable NoSQL distributed key-value type databases such as Amazon's DynamoDB, Cassandra and ScyllaDB. These databases by design are known to support write rates far more than what traditional relational databases can offer. We'll see how LSM Tree enables them to allow the write speeds that they claim, as well as how they facilitate reads.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Target audience&lt;/strong&gt;&lt;/em&gt;: You have heard of NoSQL databases such as Amazon's DynamoDB, Cassandra and embedded key value stores such as LevelDB and RocksDB and want to learn about their internals. You also have a cursory idea of different components in a database management systems (DBMS in short), particularly storage engines.&lt;/p&gt;

&lt;p&gt;This post aims to strike a balance in understanding what's written in the &lt;a href="https://www.cs.umb.edu/~poneil/lsmtree.pdf" rel="noopener noreferrer"&gt;LSM Tree paper&lt;/a&gt; and what's implemented in real world key-value stores. Even though a lot has been written about LSM Trees before, there are a lot of jargons and details about LSM Trees that are often omitted which can make them inaccessible to newcomers. This was the case with me when I started researching about LSM Trees. My goal of writing this post is to serve as an introductory resource on understanding LSM Trees and then branch off from here.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;&lt;/em&gt;: This post is an informal documentation of my research and notes for my toy database project and is a living document. I could be wrong. I want you, the readers to correct any misleading information. &lt;/p&gt;

&lt;h1&gt;
  
  
  Before we begin
&lt;/h1&gt;

&lt;p&gt;First, we need a bit of context. A typical Database Management System (DBMS in short) consists of multiple components, each responsible for handling different aspects of data storage, retrieval and management. One such component is the &lt;strong&gt;storage engine&lt;/strong&gt; which is responsible for providing a reliable interface for reading and writing data efficiently from/to the underlying storage device. It's the component that implements the two among the four big asks of databases i.e., the ACID properties: &lt;strong&gt;A&lt;/strong&gt;tomicity and &lt;strong&gt;D&lt;/strong&gt;urability. In addition to that, the performance of a storage engine matters a lot in the choice of a database as it's the component that's closest to the storage device in use. Two popular data structures for implementing storage engines are B+ Trees and LSM Trees. In this post, we'll cover LSM Trees.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why learn about LSM Trees?
&lt;/h1&gt;

&lt;p&gt;Almost all NoSQL databases use a variant of LSM Tree as their underlying storage engine, because it allows them to achieve fast write throughput and fast lookups on the primary key. Understanding how LSM Trees work will provide you with a better context in debugging any issues that you run into when using these databases. For example, in-order to tune Cassandra for a specific &lt;strong&gt;workload&lt;/strong&gt;, one needs to understand and choose between different compaction strategies, which is a critical phase in LSM Tree data management lifecycle. (covered later)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Workload&lt;/p&gt;

&lt;p&gt;A Workload in a DBMS context refers to the amount of operations that a database system can deliver in a given amount of time against a given set of metric[s] or query patterns. OLTP (Online Transaction Processing) queries and OLAP (Online Analytical Processing) queries are two among the many kinds of workload on which databases are evaluated against.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;LSM Trees are also gaining popularity as storage devices advance in their physical design from spinning disks to NAND flash SSDs and recently &lt;a href="https://en.wikipedia.org/wiki/NVDIMM" rel="noopener noreferrer"&gt;NVDIMMs&lt;/a&gt; such as Intel Optane. Traditional storage engines (based on B+ Trees) are designed for spinning disks, are slow in writes and offer only block based addressing. Today's applications, however, are write intensive and generate high volumes of data. As a result, there's a need to rethink the design of existing storage engines in DBMSs. New storage devices such as Intel Optane and other NVMs offer byte addressibility and are faster than SSDs. This has led to explorations such as &lt;a href="https://www.usenix.org/conference/fast16/technical-sessions/presentation/xu" rel="noopener noreferrer"&gt;Nova&lt;/a&gt; which is a log structured file system for persistant memory.&lt;/p&gt;

&lt;p&gt;In addition to that, learning about LSM Trees is the fastest way to get into the complicated world of database storage engine internals. They are very simple in design than B+ Tree based storage engines. So if you're someone interested in how NoSQL databases store your data, or are trying to implement a storage engine, continue reading!&lt;/p&gt;

&lt;h1&gt;
  
  
  Prologue
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Design a simple key value database
&lt;/h2&gt;

&lt;p&gt;Not taking the traditional SQL and relational path, if you were asked to design a very simple database from scratch that supports inserting data as key value pairs, how would you go about it? A possible naive implementation would be to use a file as the storage unit. Every time you receive a put request for a key and a value, you append the key value to a file:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

k1: v1
k2: v2
...
...
...



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;center&gt;&lt;code&gt;/var/local/data.db&lt;/code&gt;&lt;/center&gt;

&lt;p&gt;On a get request on a given key &lt;code&gt;k&lt;/code&gt;, you scan and find the most recent entry in the file and return back the associated value as response or a &lt;code&gt;null&lt;/code&gt; if the key does not exist. With such a design, the writes are really fast since it's just an append to the end of the file but reads have a worst case time complexity of &lt;code&gt;O(n)&lt;/code&gt;. Add a REPL interface over this with a communication protocol such as HTTP or GRPC, and you have a very trivial database server, albeit impractical for real world usage.&lt;/p&gt;

&lt;p&gt;Although our simple database doesn't handle tricky cases such as deletes, duplicates and filling up the disk space, this simple design is at the core of many real world NoSQL databases. To make this design of any practical use, real world databases often add support for features such as: transactions, crash recovery, query caching, garbage collection etc. They also use custom data structures which exploit the access latencies along the storage hierachy and uses a mix of in-memory and disk resident structures to support efficient read/write performance.&lt;/p&gt;

&lt;p&gt;This idea of an append only file of records is nothing new and there exists file systems for storage devices that use this design as their storage management logic. They are called Log-structured file systems. Log-structured file systems first appeared in the 1990s (&lt;a href="https://web.stanford.edu/~ouster/cgi-bin/papers/lfs.pdf" rel="noopener noreferrer"&gt;paper&lt;/a&gt;). It was then discovered that the same ideas and design could be used as a storage engine in databases.&lt;/p&gt;

&lt;h1&gt;
  
  
  Motivation behind LSM Trees
&lt;/h1&gt;

&lt;p&gt;To understand LSM Trees, it helps to understand why log-structured file systems (hereby LFS) came into existence as LSM Trees are largely inspired from them. LFS were proposed by Rosenblum and Osterhout in 1991. They have not seen wide adoption in the file system space, although the idea has shown up in the database world in the form of LSM Trees.&lt;/p&gt;

&lt;p&gt;During the 1990s, disk bandwidth, processor speed and main memory capacity were increasing at a rapid rate. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Disk Bandwidth: It is the total number of bytes transferred divided by the total time between the first request for service and the completion of the last transfer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With increase in memory capacity, more items could now be cached in memory for reads. As a result, read workloads were mostly absorbed by the operating system page cache. However, disk seek times were still high due to the seek and rotational latency of physical R/W head in a spinning disk. A spinning disk needs to move to a given track and sector to write the data. In the case of random I/O, with frequent read and write operations, the movement of physical disk head becomes more than the time it takes to write the data. From the LFS paper, traditional file systems utilizing a spinning disk, spends only 5-10% of disk's raw bandwidth whereas LFS permits about 65-75% in writing a new data (rest is for compaction). Traditional file systems write data at multiple places: the data block, recovery log and in-place updates to any metadata. The only bottleneck in file systems now, were during writes. As a result, there was a need to reduce writes and do less random I/O in file systems. LFS came with the idea that why not write everythng in a single log (even the metadata) and treat that as a single source of truth.&lt;/p&gt;

&lt;p&gt;Log structured file systems treat your whole disk as a log. Data blocks are written to disk in an append only manner along with their metadata (inodes). Before appending them to disk, the writes are buffered in memory to reduce the overhead of disk seeks on every write. On reaching a certain size, they are then appended to disk as a segment (64kB-1MB). A segment contains data blocks containing changes to multitude of files along with their inodes. At the same time on every write, an inode map (imap) is also updated to point to the newly written inode number. The imap is also then appended to the log on every such write so it's a just single seek away.&lt;/p&gt;

&lt;p&gt;We're not going too deep on LFS, but you get the idea. LSM Tree steals the idea of append only style updates in a log file and write buffering and has been adopted for use as a storage backend for a lot of write intensive key value database systems. Now that we know of their existence, let's look at them more closely.&lt;/p&gt;

&lt;h1&gt;
  
  
  LSM Tree deep dive
&lt;/h1&gt;

&lt;p&gt;LSM Tree is a data structure that restricts your datastore to append only operations, where your datastore is simply a log containing totally ordered key value pairs. The sort order is by key which can be any byte sequence. The values too can be any arbitrary byte sequence. For example, in Cassandra's data model, a column family (akin to a table in relational database) contains a row key (the key) and any sequence of arbitrary key values that can vary in cardinality (the value). Being append only, it means that that any kind of modification to the datastore, whether it is write, update or delete, is simply an append to the end of the log. This might sound very un-intuitive but we'll see how such a design is even possible and what challenges it poses. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The actual physical implementation of the log gets more complicated in order to exploit the storage hierarchy and the log is usually segmented across multiple files to allow for more efficient reads.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;LSM Tree is not a single data structure as a whole but combines multiple data structures that exploit the response times of different storage devices in the storage hierarchy. Being append only, it provides high rates of writes while still providing low cost reads via indexes maintained in RAM. In contrast to B+ tree based storage engine which performs in-place updates, there are no in-place updates in a LSM Tree and this helps in avoiding random I/Os. Before we delve further, let's expound on the drawbacks of using a B+ tree based database storage engine in a write intensive workload.&lt;/p&gt;

&lt;p&gt;Most traditional relational/SQL databases use a B+ Tree based storage engine. In these databases, every write has to perform not only the requested write of the record, but also perform any required metadata updates to the B+ Tree invariants which involves moving/splitting/merging nodes in the B+ Tree structure. As a result, the &lt;em&gt;Write Amplification&lt;/em&gt; is more on each write to a B+ Tree structure, thereby resulting in slower writes. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Write amplification (WA)&lt;/p&gt;

&lt;p&gt;It is the ratio of the amount of logical data to write vs the actual amount of physical data written to the underlying storage engine. The value is used as an evaluation criteria for choosing a storage device or engine. A less WA value means faster writes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;On spinning disks, the WA will certainly be visible as the write head has to perform a lot of seeks, but not so much in SSDs. But even on an SSD, the increased number of I/O per write will still degrade the lifespan of the SSD as they can only sustain a limited number of writes in their lifetime. SSDs have a copy on write semantics for page updates, and any modification first erases the original block and then rewrites the data in a new block thereafter pointing to the newly written block. The older block is then garbage collected by the SSD flash controller which also adds to the write cost. So sequential writes are beneficial to both spinning disks as well as SSDs.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: The above points don't intend to convey that relational databases are bad and should not be used, it's just suited for read heavy workloads. Having said that, a database should always be chosen according to the data model and the workload in your application. It's always a better idea to go with a use case and benchmark driven solution over tech driven solutions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dissecting LSM Tree
&lt;/h2&gt;

&lt;p&gt;LSM Trees highlights the problem that random I/O on disk has a lot of write overhead, whereas sequential write is much faster as the disk write head is right next to the place of the last written record and there is minimal rotational and seek latency.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FUMjovFx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FUMjovFx.png" alt="LSM Tree architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the paper, LSM Trees are explained more as an abstract data structure and also explains the motivation to use a tiered storage architecture. The term &lt;strong&gt;Log-structured&lt;/strong&gt; means that the data is structured one after other like an append only log. The term &lt;strong&gt;merge&lt;/strong&gt; refers to the algorithm with which data is managed in the structure. The term &lt;strong&gt;tree&lt;/strong&gt; in its name comes from the fact that data is organized into multiple levels similar to devices in the storage hierarchy in a typical computer where the top level device holds smaller subset of data and is faster to access while the lower levels holds larger segments of data and is slow to access. In a barebone setting, a LSM Tree is composed of two data structures using both RAM and and persistant disk to their advantage:&lt;/p&gt;

&lt;h2&gt;
  
  
  Memtable
&lt;/h2&gt;

&lt;p&gt;This data structure is the first point of contact for every read or write operation received by the LSM Tree. The Memtable is an in-memory structure that buffers incoming data from clients before flushing them to disk. The flush happens when the Memtable reaches a certain size threshold (~4MB in LevelDB). However, the threshold size varies depending on which database the LSM Tree is used for, keeping the RAM usage by other components in mind. What data structure to use for the Memtable typically depends upon the performance requirements but must have a property that it should provide a sorted iteration over its contents. One could naively use a Vector, or the more efficient balanced binary trees such as AVL Trees or Red Black Trees or a Skiplist (used in LevelDB). The amount of data the Memtable can hold is limited by the RAM and on exceeding the set threshold size, all of the contents of Memtable must be written to a file where items are sorted by key and a new Memtable must be created to ingest incoming writes. These persisted files are known as SSTables.&lt;/p&gt;

&lt;h2&gt;
  
  
  SSTable
&lt;/h2&gt;

&lt;p&gt;The Sorted String table (SSTable), a concept borrowed from Google's BigTable, is the on-disk format (a file) where key value entries from Memtable are flushed in sorted order. An SSTable file is created when the Memtable reaches its capacity or when compaction happens (more on that later). The data in SSTable is stored sorted to facilitate efficient read performance. Over time, there can be multiple SSTables on disk due to frequent writes to the Memtable. These are continuosly re-organized and compacted into different levels which are usually namespaced as Level 0 to Level N. The level right below (logically) the Memtable is Level 0, and can contain SSTables with overlapping keys. This means that there might be two SSTables (say &lt;code&gt;S1&lt;/code&gt; and &lt;code&gt;S2&lt;/code&gt;) in level 0 where &lt;code&gt;S1&lt;/code&gt; might contain keys in range &lt;code&gt;[a..f)&lt;/code&gt; and &lt;code&gt;S2&lt;/code&gt; might contain &lt;code&gt;[c..h]&lt;/code&gt; and the overlapping keys are &lt;code&gt;(c,d,e,f,g,h)&lt;/code&gt;. This is so because SSTables at Level 0 are plain dump of the contents of Memtable. Any deduplication of keys are deferred as a background task. The SSTable files at Level 1 and above are organized to contain only non-overlapping keys by design. Despite having a very simple structure, the SSTable architecture is capable of holding and serving petabytes of data as evident from Google's usage of them in their distributed database projects. To make them efficient, several enchancements are implemented on top of them by database systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  SSTable enchancements
&lt;/h2&gt;

&lt;p&gt;In practical implementations, SSTable files are also augmented with a SSTable summary and an index file which acts as a first point of contact when reading data from an SSTable. In this case, the SSTable is split into data files, an index file and a summary file (used in Casssandra and ScyllaDB).&lt;/p&gt;

&lt;h4&gt;
  
  
  SSTable data file
&lt;/h4&gt;

&lt;p&gt;The SSTable data files are usually encoded in a specific format with any required metadata and the key value entries are stored in chunks called blocks. These blocks may also be compressed to save on disk space. Different levels may use different compression algorithms. They also employ checksums at each block to ensure data integrity.&lt;/p&gt;

&lt;h4&gt;
  
  
  SSTable index file
&lt;/h4&gt;

&lt;p&gt;The index file lists the keys in the data file in order, giving for each key its position in the data file.&lt;/p&gt;

&lt;h4&gt;
  
  
  SSTable summary file
&lt;/h4&gt;

&lt;p&gt;The SSTable summary file is held in memory and provides a sample of keys for fast lookup in the index file. Think of it like an index for the SSTable index file. To search for a specific key, the summary file is consulted first to find a short range of position in which the key can be found and the loads up that specific offset in memory.&lt;/p&gt;

&lt;h4&gt;
  
  
  How SSTable can provide fast read access?
&lt;/h4&gt;

&lt;p&gt;If all we do is combine and merge SSTables, our SSTables would get quite large soon at the lower levels. Reads from those files will have to iterate over many keys to find the requested key. A linear scan at worst at the lowest level SSTables.&lt;br&gt;
To bring down the linear time complexity, an index over the file is an obvious solution here. We can have an in-memory index (a hashmap) which contains a mapping of keys to their byte offset in the file. With this, we are just a O(1) lookup away in the file. But if we keep all the keys in memory, we would end up using a lot of memory. What practical implementations do is that they maintain a Sparse Index of each SSTable which contains only the subset of keys in memory and utilize binary search to quickly skip ranges and narrow the search space. Everytime a compaction process occurs, the sparse indexes are also kept up-to date to allow reads to retrieve the updated data. In terms of implementation in the SSTable format, the sparse index is usually encoded at the end of the file or as a separate index file. When an SSTable is read, the sparse index is loaded into memory and is then used to find the requested key for any read request. Many practical implementations also include a bloom filter over each SSTable along with a sparse index to bail early where the key does not exist. Additionally, implementations may also memory map the SSTables in memory so lookups can happen without touching the disk. There are lot of other optimizations which are done over the SSTable which gives them a comparable performance like B+ Trees.&lt;/p&gt;

&lt;p&gt;Now that we know the core architecture of LSM Trees, let's discuss the core operations that a LSM Tree supports and how they work.&lt;/p&gt;

&lt;h1&gt;
  
  
  Operations on LSM Tree
&lt;/h1&gt;

&lt;p&gt;To be suitable for use in a key value database, a LSM Tree must support the following APIs at minimum:&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing/Updating data in a LSM Tree
&lt;/h2&gt;

&lt;p&gt;All writes in a LSM Tree are buffered in-memory and goes first to the Memtable. The Memtable is configured with a threshold (usually by size) post which all of the items in the Memtable is written to a file and is marked as part of Level 0 SSTable. The file is then marked immutable and cannot be modified. In practical implementations, the writes are also preceded by appending the entry to a Write Ahead Log (WAL) file to protect from a crash and ensure durability. In cases when the database crashes while still holding key values in Memtable, a WAL enables one to re-build and recover uncommitted entries back in the Memtable on the next restart. On reaching the Memtable threshold, the WAL is also flushed and is replaced with a new one.&lt;/p&gt;

&lt;p&gt;Updating a key value is not performed in place for already existing keys. Instead, an update to a given key will just append the new key value to the log. The older value for the data is removed at a later point in time through a phase called compaction (discussed later).&lt;/p&gt;

&lt;h2&gt;
  
  
  Deleting data in a LSM Tree
&lt;/h2&gt;

&lt;p&gt;It might come off as non-intutive the first time you discover that LSM Tree does not delete your data in-place from the log. This is so because doing so would require random I/Os thereby adding overhead to write performance.&lt;br&gt;
Since LSM Tree must hold the invariant of append only style updates to maintain the write performance, deleting things in a LSM Tree is the same as appending a key value entry to the log, instead a special byte sequence referred to as a "tombstone" is written as the value. It can be any byte sequence that should be unique enough to distinguish from other possible values. The existing older values are later removed by the compaction phase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading data in a LSM Tree
&lt;/h2&gt;

&lt;p&gt;All reads in a LSM Tree is served first from the Memtable. If the key is not found in the Memtable, it is then looked up in the most recent level L0 then L1, L2 and so on till we either find the key or return a null value. Since the SSTables are already sorted, we benefit from the ability to perform a binary search on the files to quickly narrow down the range within which the key may be found.&lt;/p&gt;

&lt;p&gt;Usually SSTables files in L0 might span the entire key space. A read will then have to access almost all files in the worst case to serve a read from L0. To keep the number of hops that reads have to do small, files in L0 are combined and moved from L0 to L1 from time to time. This helps reduce multiple I/Os to the file. In practical implementations, a Sparse Index is also used, which keeps only a range of keys in memory for each SSTable and helps reduce the number of scans required for reading a key. In addition to that, a bloom filter is also employed on each SSTable to bail early if the key does not exist in the file. This makes queries which checks if a key does not exist, very fast.&lt;/p&gt;

&lt;p&gt;During all of the above operations, our log is bound to grow to a very large size because all we do is append entries and never get rid of older duplicate/deleted entries, which brings us to the next section on compaction.&lt;/p&gt;

&lt;h1&gt;
  
  
  Enter compaction
&lt;/h1&gt;

&lt;p&gt;Over time, the number of SSTable files on disk will ultimately grow in number as flushes keep happening due to the Memtable getting full. In this case, when reading a given key, the LSM Tree will have to look into multiple SSTable files in the worst case which will result in a lot of random I/O everytime a new file is accessed. For example, in Cassandra, the values stored have many columns in them. An update to key &lt;code&gt;k&lt;/code&gt; at time &lt;code&gt;t1&lt;/code&gt;, might add 4 column values &lt;code&gt;(k -&amp;gt; (v1, v2, v3, v4))&lt;/code&gt;. At a later point in time &lt;code&gt;t2&lt;/code&gt;, the same key &lt;code&gt;k&lt;/code&gt; might update the 4th column value to some other value and might delete the 2nd column value &lt;code&gt;(k -&amp;gt; (v1, v3, v4_1))&lt;/code&gt;. When the same key &lt;code&gt;k&lt;/code&gt; is read at a later time &lt;code&gt;t3&lt;/code&gt;, cassandra will need to aggregate updates from both of the changes above to build an updated value for &lt;code&gt;k&lt;/code&gt;. Now if these changes for the given key &lt;code&gt;k&lt;/code&gt; is spread across multiple SSTable files, reads will need to perform a lot of random I/O to retrieve the updated value. This deteriorates the read performance and so there needs to be a way to combine these updates in a single file if possible. This is done by a phase called compaction.&lt;/p&gt;

&lt;p&gt;Compaction is a critical phase of LSM Tree data management lifecycle allowing them to be used for extended periods of time in practical systems. Think of it like a garbage collector for the LSM Tree. It keeps the disk usage and read/write performance of the LSM Tree in check. The core algorithm utilized by compaction is the k-way merge sort algorithm adapted to SSTables. I wrote a &lt;a href="https://creativcoder.dev/merge-k-sorted-arrays-rust" rel="noopener noreferrer"&gt;post&lt;/a&gt; on this if you are unfamiliar with the algorithm. In summary, we keep pulling the next key value pair from given k lists of entries (based on whatever the sort order is) and put them one by one in a new SSTable file. During the process, we remove entries which are older or merge them with newer entries and delete older entries which have a tombstone value in the recent entry.&lt;/p&gt;

&lt;p&gt;Apart from reducing multiple I/Os, another problem that compaction helps solve is that, there might be multiple old entries for a given key or deleted tombstone entries which ends up taking space on disk. This happens when a delete or an update is performed for an existing key at a later time. It then becomes essential to reclaim disk space for outdated and deleted keys and compaction does this by discarding older or deleted entries when creating a new SSTable file.&lt;/p&gt;

&lt;p&gt;In terms of implementation, a dedicated background thread is used to perform compaction. Compaction can either be done manually by calling an API or automatically as a background task when certains conditions are met. The compaction process can be synchronous or asynchronous depending on what consistancy guarantees are configured for the LSM Tree store. The read write performance of a LSM Tree is greatly impacted by how compaction happens. As an optimization, there might be multiple dedicated compactor threads running at a given point in time (as in RocksDB) to compact SSTables files. The compaction thread is also responsible for updating the Sparse Index post any merge, to point to the new offsets of keys in the new SSTable file. Everytime the size of files in level 0 reaches the configured threshold, a file or multiple of them is taken and merged with all overlapping keys of the next level (level 1). The same happens with level 1 to level 2 and likewise when those levels reach their capacity. Now, the metric to determine when levels become full can be different based the compaction strategy. Different compaction strategies are utilized based on the requirements and they determine the shape of the SSTables at all the levels.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compaction strategies
&lt;/h2&gt;

&lt;p&gt;A compaction strategy must choose which files to compact, and when to compact them. There are a lot of different compaction strategies that impact the read/write performance and the space utilization in the LSM Tree. Some of the popular compaction strategies that are used in production systems are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Size-tiered compaction stratey - This is write optimized compaction strategy and is the default one used in ScyllaDB and Cassandra. But it has high space amplification, so other compaction strategies such as leveled compaction were developed.&lt;/li&gt;
&lt;li&gt;Leveled compaction strategy - Improves over size-tiered and reduces read amplification as well as space amplification. This is the default in LevelDB.&lt;/li&gt;
&lt;li&gt;Time windowed compaction strategy - Used for time series databases. In this strategy, a time window is used post which compaction is triggered.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The above are not the only strategies and various systems have developed their own such as the hybrid compaction strategy in ScyllaDB.&lt;/p&gt;

&lt;h1&gt;
  
  
  Drawbacks of LSM Trees
&lt;/h1&gt;

&lt;p&gt;Any technology introduced, brings with it its own set of tradeoffs. LSM Tree is no different. The main disadvantage of LSM Tree is the cost of compaction which affects read and write performance. Compaction is the most resource intensive phase of LSM Tree due to compression/decompression of data, copying and comparision of keys involved in the process. A chosen compaction strategy must try to minimize read amplification, write amplification and space amplification. Another drawback of LSM Tree is the extra space required to perform compaction. This is certainly visible in size tiered compaction strategy and so other compaction strategies like leveled compaction are used. LSM Tree also makes reads slow in the worst case. Due to the append only nature, reads will have to search in SSTable at the lowest level. There's file I/O involved in seeks which makes reads slow.&lt;/p&gt;

&lt;p&gt;Despite their disadvantages, LSM Trees have been in use in quite a lot of database systems and has become the de-facto pluggable storage engine in lot of storage scenarios.&lt;/p&gt;

&lt;h1&gt;
  
  
  LSM Trees in the wild
&lt;/h1&gt;

&lt;p&gt;LSM trees have been used in many NoSQL databases as their storage engine. They are also used as embedded databases and for any simple but robust data persistance uses cases such as search engine indexes.&lt;/p&gt;

&lt;p&gt;One of the first projects to make use of LSM Trees was the Lucene search engine (1999). Google BigTable (2005), a distributed database also uses LSM Tree in their underlying tablet server design and is being used for holding petabytes of data for Google Crawl and analytics. It was then discovered by BigTable authors that the design of BigTable's "tablet" (storage engine node) could be abstracted out and be used as a key value store.&lt;/p&gt;

&lt;p&gt;Born off of that, came &lt;a href="https://github.com/google/leveldb" rel="noopener noreferrer"&gt;LevelDB&lt;/a&gt; (2011) by the same authors which uses LSM Tree as its underlying data structure. This gave rise to pluggable storage engines and embedded databases. Around the same time in 2007, Amazon came up with &lt;a href="https://aws.amazon.com/dynamodb/" rel="noopener noreferrer"&gt;DynamoDB&lt;/a&gt; which uses the same underlying LSM Tree structure along with a masterless distributed database design.&lt;/p&gt;

&lt;p&gt;Dynamo DB inspired the design of &lt;a href="https://cassandra.apache.org/" rel="noopener noreferrer"&gt;Cassandra&lt;/a&gt; (2008), which is an open source distributed NoSQL database. Cassandra inspired &lt;a href="https://www.scylladb.com/" rel="noopener noreferrer"&gt;ScyllaDB&lt;/a&gt; (2015) and others. &lt;a href="https://www.influxdata.com/" rel="noopener noreferrer"&gt;InfluxDB&lt;/a&gt; (2015), a time series database also uses LSM Tree based storage engine called Time structured merge tree.&lt;/p&gt;

&lt;p&gt;Inspired from LevelDB, Facebook forked LevelDB and created &lt;a href="https://github.com/facebook/rocksdb" rel="noopener noreferrer"&gt;RocksDB&lt;/a&gt; (2012), a more concurrent and efficient key value store that uses multi-threaded compaction to improve read and write performance. Recently Bytedance, the company behind TikTok has also released a key value store called &lt;a href="https://github.com/bytedance/terarkdb" rel="noopener noreferrer"&gt;terakdb&lt;/a&gt; that improves over RocksDB. &lt;a href="https://github.com/spacejam/sled" rel="noopener noreferrer"&gt;Sled&lt;/a&gt; is another embedded key value store in Rust, that uses a hybrid architecture of B+ Trees and LSM Tree (Bw Trees). These fall under the category of embedded data stores.&lt;/p&gt;

&lt;p&gt;I hope by now you have a pretty good idea about LSM Trees. For those who are keen to dig deeper, a few links to original papers are down below. Until next time!&lt;/p&gt;

&lt;h4&gt;
  
  
  References
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://people.eecs.berkeley.edu/~brewer/cs262/LFS.pdf" rel="noopener noreferrer"&gt;LFS paper&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.cs.umb.edu/~poneil/lsmtree.pdf" rel="noopener noreferrer"&gt;LSM Tree paper&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;As always, you can support this blog by donating on the following links:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ko-fi.com/P5P71YZ0L" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fko-fi.com%2Fimg%2Fgithubbutton_sm.svg" alt="ko-fi"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>keyvalue</category>
      <category>database</category>
      <category>nosql</category>
      <category>lsmtree</category>
    </item>
    <item>
      <title>Merge k sorted arrays in Rust</title>
      <dc:creator>creativcoder</dc:creator>
      <pubDate>Mon, 07 Dec 2020 04:21:10 +0000</pubDate>
      <link>https://dev.to/creativcoder/merge-k-sorted-arrays-in-rust-1b2f</link>
      <guid>https://dev.to/creativcoder/merge-k-sorted-arrays-in-rust-1b2f</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Faoh6yf5y0jv5q7kqad0e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Faoh6yf5y0jv5q7kqad0e.png" alt="Cover"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Originally posted on &lt;a href="https://creativcoder.dev/merge-k-sorted-arrays-rust" rel="noopener noreferrer"&gt;creativcoder.dev&lt;/a&gt;
&lt;/h6&gt;

&lt;p&gt;The other day, I was reading about LSM Tree based database storage engines (specifically, the LevelDB &lt;a href="https://github.com/google/leveldb/blob/master/doc/impl.md" rel="noopener noreferrer"&gt;docs&lt;/a&gt;) where I came to know about a phase called compaction. LSM Tree based database storage engines are key-value storage systems where every operation is append only to favour less &lt;a href="https://en.wikipedia.org/wiki/Write_amplification" rel="noopener noreferrer"&gt;write amplification&lt;/a&gt; and to reduce latency. LevelDB persists data file segments to disk (when the in-memory table hits a threshold) in sorted order to support efficient read queries. Even operations such as deletes or updates appends new entries to the underlying storage and this often leads to keys that are obsolete but still remain on disk and that increases disk usage. To overcome this, they often use a phase called &lt;em&gt;compaction&lt;/em&gt; where several sorted files are merged into single file to remove old data records in background. In order to implement a similar compaction strategy in my toy database project, I used the &lt;code&gt;merge&lt;/code&gt; sub-routine from merge sort, generalizing it to k sorted arrays. In this post, I write about the implementation the merge k algorithm in Rust. If you know the merge sub-routine from merge sort, you should feel right at home understanding the algorithm.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Before formalizing the solution, we'll re-state the problem again with examples and reason up from there to come up with an implementation in Rust.&lt;/p&gt;

&lt;p&gt;We are given &lt;code&gt;k&lt;/code&gt; array of items that are sorted. The problem is to implement a function that given &lt;code&gt;k&lt;/code&gt; sorted arrays, merges them and returns an array where all the elements are in sorted order.&lt;/p&gt;

&lt;p&gt;For example, If we are given 2 sorted arrays:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;a = [3, 5]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;b = [2, 7]&lt;/code&gt; where &lt;code&gt;k = 2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then the merged array we get, would be &lt;code&gt;c = [2, 3, 5, 7]&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Obvious naive solution
&lt;/h2&gt;

&lt;p&gt;It's always a good idea to start with what you already know as the thinking lends itself to revealing more about the problem at hand. So, the obvious approach to solve this would be to just concatenate the two arrays and sort them. Here's a solution in Rust:&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;let&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&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="mi"&gt;5&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;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&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="mi"&gt;7&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;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nf"&gt;.concat&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="nf"&gt;.sort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nd"&gt;dbg!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&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;That was quite easy, but it does have a &lt;code&gt;O(n*k * log n*k)&lt;/code&gt; worst case time complexity, where &lt;code&gt;n&lt;/code&gt; is the size of the resulting vector and &lt;code&gt;k&lt;/code&gt; is the number of arrays. Can we do better?&lt;/p&gt;

&lt;p&gt;Let's try a different approach. Without thinking about the implementation, how would you normally put these elements in order by hand? Let's distill down the above example and give it a thought with a case by case analysis. &lt;/p&gt;

&lt;h4&gt;
  
  
  Case 1:
&lt;/h4&gt;

&lt;p&gt;Let's say for example, the arrays have only 1 element in them:&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="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&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="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, it's pretty trivial. We just compare the first item with the second and take the smallest of the two, and insert it as first element in the resulting array: &lt;code&gt;[2]&lt;/code&gt;. What remains is &lt;code&gt;3&lt;/code&gt; from &lt;code&gt;a&lt;/code&gt; which we then append giving us &lt;code&gt;[2, 3]&lt;/code&gt; as the merged sequence.&lt;/p&gt;

&lt;h4&gt;
  
  
  Case 2:
&lt;/h4&gt;

&lt;p&gt;Now, let's consider if one of the arrays have more than one element:&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="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&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="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&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="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, we'll start again with the first item in both arrays and pick the smallest of the two items which is &lt;code&gt;2&lt;/code&gt;. The next item to compare is &lt;code&gt;3&lt;/code&gt; (from &lt;code&gt;a&lt;/code&gt;) and &lt;code&gt;5&lt;/code&gt; (from &lt;code&gt;b&lt;/code&gt;), among which &lt;code&gt;3&lt;/code&gt; is chosen as the next smallest element. At this point in time, we have exhausted all items in array &lt;code&gt;a&lt;/code&gt;. Now, whatever remains to be put in the merged array has to be from array &lt;code&gt;b&lt;/code&gt;. This is because of the invariant that we always pick the smallest item in each iteration so if all items from array &lt;code&gt;a&lt;/code&gt; are exhausted, all remaining elements must be greater than last element in &lt;code&gt;a&lt;/code&gt;. So we append &lt;code&gt;5&lt;/code&gt; from &lt;code&gt;b&lt;/code&gt; to our merged array to give us: &lt;code&gt;[2, 3, 5]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;From the dry run of the above two cases, you must have already thought of using two variables as indexes over the arrays and walk over them one by one, taking the next smallest element in each iteration until one of them exhausts, and then copy all the items from the remaining array to our merged sequence. Sounds simple? Let's implement that:&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation of merge k, where k = 2
&lt;/h2&gt;

&lt;p&gt;To simplify the implementation for readability, we'll limit the items to integer (&lt;code&gt;i32&lt;/code&gt;) values. Once we have the implementation in place, one can refactor it easily to make it generic over any &lt;code&gt;T&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here's how we can implement the above index pointer based solution in Rust:&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;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&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;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&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="k"&gt;-&amp;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="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&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="mi"&gt;0&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;sorted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&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;remaining&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;remaining_idx&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;sorted&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
            &lt;span class="n"&gt;i&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;remaining&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;remaining_idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;j&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="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="n"&gt;sorted&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
            &lt;span class="n"&gt;j&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;remaining&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;remaining_idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&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="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;remaining_idx&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;remaining&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sorted&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;remaining&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;sorted&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have the &lt;code&gt;merge&lt;/code&gt; function defined that takes in two slices of integers aka reference to an array of integers and returns a &lt;code&gt;Vec&amp;lt;i32&amp;gt;&lt;/code&gt; (a heap allocated value). Within &lt;code&gt;merge&lt;/code&gt;, we create two indexes &lt;code&gt;i, j&lt;/code&gt; that start with &lt;code&gt;0&lt;/code&gt;. We also create a &lt;code&gt;remaining&lt;/code&gt; and &lt;code&gt;remaining_idx&lt;/code&gt; to point to the array that gets left after all items from the other array gets exhausted. Next, we run a &lt;code&gt;loop {}&lt;/code&gt;, where we pick the smallest item, push it to &lt;code&gt;sorted&lt;/code&gt; and increment the respective index. We also do an additional check if we reach the end on one of the arrays and assign &lt;code&gt;remaining&lt;/code&gt; and &lt;code&gt;remaining_idx&lt;/code&gt; accordingly. After the loop, we loop over the &lt;code&gt;remaining&lt;/code&gt; array items and push to &lt;code&gt;sorted&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But, the above solution works only for 2 arrays. We need to generalize the solution to k sorted arrays.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generalizing to k sorted arrays
&lt;/h2&gt;

&lt;p&gt;How would one extend the above solution to k sorted collection of items?&lt;/p&gt;

&lt;p&gt;Well it turns out that now we need to keep k pointers to k arrays and pick the smallest item out of k. It's easy enough to write code to keep track of the pointers, if we have let's say &amp;lt; 10 or &amp;lt; 100 arrays to be merged. Or instead of keeping pointers, we could store an array of indexes into the arrays. That's another solution that works again for smaller values of k. But, it's not a convenient or maintainable code to write when we have very large arrays to be merged. Moreover, the number of comparision increases linearly as k increases.&lt;/p&gt;

&lt;p&gt;Following along the same solution, let's think about what we need to find from the k arrays at the first iteration of the loop. That's right, we need to find the minimum from k items. This might give you a hint of using some data structure that supports getting minimum item from the &lt;code&gt;k&lt;/code&gt; items. One data structure that comes to my mind is the heap data structure. In particular, a min-heap data structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter the min heap
&lt;/h2&gt;

&lt;p&gt;A Heap is a complete binary tree (nodes are inserted breadth first left to right) where there's a relation between parent and child nodes. This is the heap property. There are two variants of heap: min heap and max heap. In min heap the every parent node is smaller than the child and conversely for the max heap. At minimum, any implementation supports three key APIs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;inserting - Adds an element to the heap&lt;/li&gt;
&lt;li&gt;removing - Removes an element to the heap&lt;/li&gt;
&lt;li&gt;heapify - rebalances the tree while maintaining the heap property.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At all times the heap property must be maintained when inserting or removing items from the heap. Internally the heap uses the &lt;code&gt;siftDown&lt;/code&gt; and &lt;code&gt;bubbleUp&lt;/code&gt; sub-routines to maintain the heap property.&lt;/p&gt;

&lt;p&gt;So using a min-heap, we can insert the first k items into the array. Then we keep popping until our heap is empty and keeping the array indexes.&lt;/p&gt;

&lt;p&gt;To implement this, we need to modify our solution a bit.&lt;/p&gt;

&lt;p&gt;Our &lt;code&gt;merge&lt;/code&gt; method now takes in a &lt;code&gt;Vec&amp;lt;Vec&amp;lt;i32&amp;gt;&amp;gt;&lt;/code&gt; as a parameter (an array of array of signed integers):&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;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arrays&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;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;&amp;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;Next, let's create an &lt;code&gt;Item&lt;/code&gt; struct that will hold references to the k arrays and their respective index as their iteration state. The index will tell us where in our array we are currently at. This &lt;code&gt;Item&lt;/code&gt; instance will be the element that goes in our min heap.&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="nd"&gt;Eq)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&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="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now &lt;code&gt;Item&lt;/code&gt; doesn't convey how they should be compared, as it's a new data type we've defined. So we need to tell the type system how they should be compared. Doing this is easy and we'll just need to implement a few traits and defer the comparision to the elements of the array using a helper method &lt;code&gt;get_item&lt;/code&gt; (we define). On the &lt;code&gt;Item&lt;/code&gt; struct we'll implement the required traits (&lt;code&gt;PartialEq&lt;/code&gt;, &lt;code&gt;PartialOrd&lt;/code&gt;, &lt;code&gt;Ord&lt;/code&gt;) so that it can be inserted into min-heap:&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;PartialEq&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&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;fn&lt;/span&gt; &lt;span class="nf"&gt;eq&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="n"&gt;other&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;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="nf"&gt;.get_item&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="nf"&gt;.get_item&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="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;PartialOrd&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&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;fn&lt;/span&gt; &lt;span class="nf"&gt;partial_cmp&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="n"&gt;other&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;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Ordering&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;self&lt;/span&gt;&lt;span class="nf"&gt;.get_item&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.partial_cmp&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;other&lt;/span&gt;&lt;span class="nf"&gt;.get_item&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="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Ord&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&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;fn&lt;/span&gt; &lt;span class="nf"&gt;cmp&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="n"&gt;other&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="n"&gt;Ordering&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="nf"&gt;.get_item&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.cmp&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;other&lt;/span&gt;&lt;span class="nf"&gt;.get_item&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;We also have a few helper methods &lt;code&gt;new&lt;/code&gt; and &lt;code&gt;get_item&lt;/code&gt; purely for convenience.&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&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;fn&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&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="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&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;Self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;idx&lt;/span&gt;
        &lt;span class="p"&gt;}&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;get_item&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;i32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.idx&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;Once we have the required traits implemented for &lt;code&gt;Item&lt;/code&gt;, we'll then implement the new &lt;code&gt;merge&lt;/code&gt; algorithm:&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;use&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;collections&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;BinaryHeap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&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;cmp&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Reverse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&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;cmp&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Ordering&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;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arrays&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;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;&amp;gt;&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;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="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;sorted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&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;heap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;BinaryHeap&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;with_capacity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arrays&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;arrays&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;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Item&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="n"&gt;arr&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;heap&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;heap&lt;/span&gt;&lt;span class="nf"&gt;.is_empty&lt;/span&gt;&lt;span class="p"&gt;()&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;it&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;heap&lt;/span&gt;&lt;span class="nf"&gt;.pop&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;sorted&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt;&lt;span class="nf"&gt;.get_item&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt;&lt;span class="py"&gt;.idx&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt;&lt;span class="py"&gt;.idx&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt;&lt;span class="py"&gt;.arr&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;heap&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&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="n"&gt;sorted&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We create a &lt;code&gt;Vec&lt;/code&gt; that will hold our merged items. We then create a &lt;code&gt;BinaryHeap&lt;/code&gt; instance and push all items in &lt;code&gt;arrays&lt;/code&gt; as an &lt;code&gt;Item&lt;/code&gt; with the start index &lt;code&gt;0&lt;/code&gt;. We then wrap &lt;code&gt;item&lt;/code&gt; with &lt;code&gt;Reverse&lt;/code&gt; (as it's a max heap by default) and push it to heap.&lt;/p&gt;

&lt;p&gt;Next, we run a loop while we still have elements in heap. Within the loop, we get the smallest item by &lt;code&gt;heap.pop()&lt;/code&gt; and push it to &lt;code&gt;sorted&lt;/code&gt; and increment the item's index by 1. Because we might still have items in the heap, we check for that and push it back in the last line.&lt;/p&gt;

&lt;p&gt;Finally once we are done, we return the &lt;code&gt;sorted&lt;/code&gt; array.&lt;/p&gt;

&lt;p&gt;For this solution our complexity now reduces to &lt;code&gt;O(n*k * Log(k))&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Finally let's test this out on a sample dataset:&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;let&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&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="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&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;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&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;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nd"&gt;dbg!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&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;Final code: &lt;a href="https://gist.github.com/creativcoder/20fda0f1a947bf2af3b93ab394d6bacb" rel="noopener noreferrer"&gt;https://gist.github.com/creativcoder/20fda0f1a947bf2af3b93ab394d6bacb&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Taking it a step further
&lt;/h2&gt;

&lt;p&gt;An optimization on top of this would be to stream sorted values as they are processed by exposing an iterator over the &lt;code&gt;k&lt;/code&gt; items in heap.&lt;/p&gt;

&lt;p&gt;With that said, I am open to suggestions, improvements to the solution and you can do so with comments below. Until next time!&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>database</category>
      <category>merge</category>
      <category>rust</category>
    </item>
    <item>
      <title>How to setup NextJS with TailwindCSS 🌊</title>
      <dc:creator>creativcoder</dc:creator>
      <pubDate>Sun, 06 Dec 2020 18:05:09 +0000</pubDate>
      <link>https://dev.to/creativcoder/how-to-setup-nextjs-with-tailwindcss-4kp6</link>
      <guid>https://dev.to/creativcoder/how-to-setup-nextjs-with-tailwindcss-4kp6</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwkne1amv5nhxnp1553ps.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwkne1amv5nhxnp1553ps.png" alt="Cover"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Originally posted on &lt;a href="https://creativcoder.dev/setup-nextjs-tailwind" rel="noopener noreferrer"&gt;creativcoder.dev&lt;/a&gt;
&lt;/h6&gt;

&lt;p&gt;Lately, I've been dabbling with frontend projects and as a result, have been looking for the best out-of-the-box frontend stack. I found NextJS with TailwindCSS checks most of my requirements. As a backend engineer who does not want to dabble  much with setting up a website or a project with hundreds of webpack plugins and manual configurations, I think NextJS with TailwindCSS provides a great rapid prototyping experience.&lt;/p&gt;

&lt;p&gt;So I thought of putting together an article as a note to self about setting up TailwindCSS with NextJS. Hopefully this will also be helpful to you if you are starting a project with the same stack.&lt;/p&gt;

&lt;p&gt;First, a bit of intro to these. &lt;/p&gt;

&lt;p&gt;NextJS is a framework built on top of react with all the three lettered jazz (SSR and friends). The website explains it better than I do: &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;https://nextjs.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=3u_vIdnJYLc&amp;amp;t=10s" rel="noopener noreferrer"&gt;TailwindCSS&lt;/a&gt; on the other hand is the next best thing to happen to CSS ecosystem after Bootstrap (in my opinion). It let's one prototype and experiment with UIs quickly without having to switch back and forth between your HTML and CSS files because in TailwindCSS, what you get is lego like blocks of CSS classes which you can mix and mash to create beautiful layouts. Later, when these classes get too big, you can extract the them into their own styled components using the &lt;code&gt;@apply&lt;/code&gt; directive. It's like writing a bunch of lines of code and then extracting them out as functions. Quite amazing! As someone who does mostly backend, this is certainly an efficient way to prototype and get feedback on UI design. It reduces the context switch by a lot!&lt;/p&gt;

&lt;p&gt;With that introduction out of the way, let's dive right in!&lt;/p&gt;

&lt;p&gt;First, we'll create a NextJS app by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-next-app next-tailwind
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;npx&lt;/code&gt; allows you to run binary packages from npm directly without installing them locally. Then, we'll cd into the folder and add the &lt;code&gt;tailwindcss&lt;/code&gt; package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd next-tailwind
yarn add tailwindcss
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once that's added, we move in our &lt;code&gt;styles&lt;/code&gt; folder and we'll create a &lt;code&gt;globals.css&lt;/code&gt; file (might already be there for you):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch styles/globals.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To this file, we'll add the following tailwind directives and remove any existing styles if any:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@tailwind base;
@tailwind components;
@tailwind utilities;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The doc explains what they do: &lt;a href="https://tailwindcss.com/docs/functions-and-directives" rel="noopener noreferrer"&gt;https://tailwindcss.com/docs/functions-and-directives&lt;/a&gt;&lt;br&gt;
We'll also add a tailwind configuration file as you might need to customize the built-in style components classes it provides (injected via the above directives). So we'll run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx tailwindcss init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a &lt;code&gt;tailwind.config.js&lt;/code&gt; file at the root with basic fixtures for all customizable options:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tailwind.config.js&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;purge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;darkMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// or 'media' or 'class'&lt;/span&gt;
  &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&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="na"&gt;variants&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&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="na"&gt;plugins&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;One can also pass &lt;code&gt;--full&lt;/code&gt; to populate the full list of configurable fields.&lt;/p&gt;

&lt;p&gt;The final step is to add a postcss configuration file as we'll need to convert the contents of &lt;code&gt;globals.css&lt;/code&gt; and any tailwind classes we write in on our page to plain CSS for our browser to understand. We'll create a configuration file for postcss at root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch postcss.config.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where we'll add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// postcss.config.js&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tailwindcss&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;p&gt;We specify the plugin we want to use which is &lt;code&gt;tailwindcss&lt;/code&gt;. With that, our setup is complete. Let's take it up for spin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To try tailwind, let's clear everything in &lt;code&gt;pages/index.js&lt;/code&gt; and paste the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pages/index.js&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Home&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bg-yellow-300 flex h-screen justify-center items-center"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bg-white p-5 shadow-lg duration-200 hover:bg-yellow-200 transform hover:-skew-x-12"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Hello tailwind next
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&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;That's a classic centered &lt;code&gt;div&lt;/code&gt; example we've just created using a bunch of tailwind classes sprinkled in between.&lt;/p&gt;

&lt;p&gt;Our parent div is a flex wrapper &lt;code&gt;"flex"&lt;/code&gt; with a yellow background &lt;code&gt;"bg-yellow-300"&lt;/code&gt; with screen height &lt;code&gt;"h-screen"&lt;/code&gt; where items on main-axis (horizontal) are aligned as &lt;code&gt;"justify-center"&lt;/code&gt; and items on cross-axis (vertical) are &lt;code&gt;"items-center"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The button within, has a white background &lt;code&gt;"bg-white"&lt;/code&gt; with a shadow &lt;code&gt;"shadow-lg"&lt;/code&gt; and a padding &lt;code&gt;"p-5"&lt;/code&gt;. We also put some styles on the hover state: &lt;code&gt;"hover:bg-yellow-200 transform hover:-skew-x-12 duration-200"&lt;/code&gt;. Here we are just saying: on hover make the background yellow and skew it clockwise (-12deg) and transition with 200ms.&lt;/p&gt;

&lt;p&gt;Let's head over to our browser to see it in effect:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fitr5o87lsxkugfi7zo3y.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fitr5o87lsxkugfi7zo3y.jpg" alt="Tailwind demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Neat! &lt;/p&gt;

&lt;p&gt;As you can see, we did all of this without ever touching any CSS file. Also, these class names are quite intuitive and having worked multiple times with tailwind, I now rarely need to look them up during rapid prototyping, which cuts another chunk of time spent looking at the docs.&lt;/p&gt;

&lt;p&gt;It was with tailwind that I was able to quickly create a very simple landing page for &lt;a href="https://creativcoder.dev/avrow" rel="noopener noreferrer"&gt;avrow&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As an added note: &lt;a href="https://play.tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind playground&lt;/a&gt; is an online tailwind playground that you can use to rapidly prototype UIs.&lt;/p&gt;

&lt;p&gt;And that's how you setup tailwind with NextJS. Until next time.&lt;/p&gt;

&lt;p&gt;Source code for this post is available at: &lt;a href="https://github.com/creativcoder/next-tailwind" rel="noopener noreferrer"&gt;https://github.com/creativcoder/next-tailwind&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cheers!&lt;/p&gt;

</description>
      <category>tailwindcss</category>
      <category>react</category>
      <category>nextjs</category>
      <category>frontend</category>
    </item>
    <item>
      <title>How to run Rust on Arduino Uno</title>
      <dc:creator>creativcoder</dc:creator>
      <pubDate>Thu, 20 Aug 2020 08:11:12 +0000</pubDate>
      <link>https://dev.to/creativcoder/how-to-run-rust-on-arduino-uno-40c0</link>
      <guid>https://dev.to/creativcoder/how-to-run-rust-on-arduino-uno-40c0</guid>
      <description>&lt;p&gt;Originally posted on: &lt;a href="https://creativcoder.dev/rust-on-arduino-uno" rel="noopener noreferrer"&gt;creativcoder.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the time of writing this, about a month ago, the rust-avr fork was merged &lt;a href="https://github.com/rust-lang/rust/issues/44052#issuecomment-663394401" rel="noopener noreferrer"&gt;upstream&lt;/a&gt;. This means that you can now compile Rust programs for the avr microcontroller board by just running &lt;code&gt;cargo +nightly build&lt;/code&gt;, providing a &lt;code&gt;.cargo/config.toml&lt;/code&gt; for your target (&lt;code&gt;avr-unknown-unknown&lt;/code&gt;). That's huge!&lt;/p&gt;

&lt;p&gt;I have always been fascinated with the idea of using code to manipulate and affect physical objects. This is probably going to be a series of blog posts on my adventures with Rust on Arduino and maybe ESP8266 and discovery F3 in future. (I have these lying around too). Kicking off the series with this first post.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Target audience&lt;/em&gt;: This post is written with beginner to intermediate folks in mind who want a head start with embedded systems in Rust with Arduino. Once you have gone through this post, you may wanna go through the through the basics on &lt;a href="https://rust-embedded.github.io/book/intro/index.html" rel="noopener noreferrer"&gt;embedded rust book&lt;/a&gt;. The code in the post is compiled on a Linux machine (Arch linux) with Rust compiler version: &lt;code&gt;rustc 1.47.0-nightly (22ee68dc5 2020-08-05)&lt;/code&gt;.&lt;/p&gt;




&lt;p&gt;We'll take a whirlwind tour on how to run Rust on the Arduino Uno, which is probably the most widely known and used development board in the hobbyist embedded domain. The &lt;a href="https://store.arduino.cc/usa/arduino-uno-rev3" rel="noopener noreferrer"&gt;Arduino Uno&lt;/a&gt; is based on the ATmega328P, which is an 8 bit microcontroller falling under the family AVR. AVR is a family of micro-controllers developed since 1996 by Atmel, which was later acquired by Microchip technology. If you wanna read more about that, head over here: &lt;a href="https://book.avr-rust.com/001-introduction.html" rel="noopener noreferrer"&gt;AVR-Rust book&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With that brief history aside, let's get into it!&lt;/p&gt;

&lt;p&gt;We'll do the hello world of arduino which is blinking an LED. It's a very simple exercise, but there's a lot to learn as a beginner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up our project
&lt;/h2&gt;

&lt;p&gt;First, we'll create a new cargo project by running:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

cargo new rust-arduino-blink


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We'll need to cross compile our project for the avr target (target triple:&lt;code&gt;avr-unknown-unknown&lt;/code&gt;).&lt;br&gt;
For this we'll need to switch to the nightly toolchain as some of the dependent crates use unstable features to make all of this happen. So we'll run:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

rustup override &lt;span class="nb"&gt;set &lt;/span&gt;nightly


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The above command overrides the toolchain of choice for only our current directory to be nightly.&lt;/p&gt;

&lt;p&gt;Then we'll install the required packages:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

pacman &lt;span class="nt"&gt;-S&lt;/span&gt; avr-gcc


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;avr-gcc&lt;/code&gt; package is required to use the linker.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

pacman -S arduino-avr-core


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;arduino-avr-core&lt;/code&gt; package contains utilities such as &lt;a href="https://www.nongnu.org/avrdude/" rel="noopener noreferrer"&gt;avrdude&lt;/a&gt; which is a tool to upload and manipulate ROM and EEPROM contents of microcontrollers using the in-system programming technique.&lt;/p&gt;

&lt;p&gt;I am on an arch linux distro (endeavour OS) where &lt;code&gt;pacman&lt;/code&gt; is our package manager.&lt;/p&gt;

&lt;p&gt;Then, under &lt;code&gt;Cargo.toml&lt;/code&gt; we'll add the following dependencies:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;

&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="c"&gt;# A panic handler is needed.  This is a crate with the most basic one.&lt;/span&gt;
&lt;span class="py"&gt;panic-halt&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.2.0"&lt;/span&gt;

&lt;span class="nn"&gt;[dependencies.arduino-uno]&lt;/span&gt;
&lt;span class="py"&gt;git&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://github.com/Rahix/avr-hal"&lt;/span&gt;
&lt;span class="py"&gt;rev&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"536c5d"&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;avr-hal&lt;/code&gt; is a cargo workspace that contains a bunch of crates segregated by boards where the &lt;code&gt;arduino-uno&lt;/code&gt; crate is one&lt;br&gt;
of them. Thanks to &lt;a href="https://github.com/Rahix/avr-hal" rel="noopener noreferrer"&gt;Rahix&lt;/a&gt; for putting this together.&lt;/p&gt;

&lt;p&gt;We'll also need to add build metadata for cargo for the avr target. We'll create a file &lt;code&gt;avr-atmega328p&lt;/code&gt; at our project root with the following contents:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&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="nl"&gt;"llvm-target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"avr-unknown-unknown"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cpu"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"atmega328p"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target-endian"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"little"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target-pointer-width"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"16"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target-c-int-width"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"16"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"os"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target-env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target-vendor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"arch"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"avr"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"data-layout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nl"&gt;"executables"&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;"linker"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"avr-gcc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"linker-flavor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gcc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"pre-link-args"&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="nl"&gt;"gcc"&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;"-Os"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"-mmcu=atmega328p"&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="nl"&gt;"exe-suffix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;".elf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"post-link-args"&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="nl"&gt;"gcc"&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;"-Wl,--gc-sections"&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="nl"&gt;"singlethread"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"no-builtins"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nl"&gt;"no-default-libraries"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nl"&gt;"eh-frame-header"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&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;and reference it in &lt;code&gt;.cargo/config.toml&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;

&lt;span class="nn"&gt;[build]&lt;/span&gt;
&lt;span class="py"&gt;target&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"avr-atmega328p.json"&lt;/span&gt;

&lt;span class="nn"&gt;[unstable]&lt;/span&gt;
&lt;span class="py"&gt;build-std&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"core"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;With that, our build configuration is complete.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's write some code
&lt;/h2&gt;

&lt;p&gt;With the dependencies aside, let's add code under &lt;code&gt;main.rs&lt;/code&gt; and go through it incrementally:&lt;/p&gt;

&lt;p&gt;(Quick tip: You can run &lt;code&gt;cargo doc --open&lt;/code&gt; in your directory and have a documentation of this project along with its dependencies for ready reference)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// main.rs&lt;/span&gt;

&lt;span class="nd"&gt;#![no_std]&lt;/span&gt;
&lt;span class="nd"&gt;#![no_main]&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;First we need to specify a few global attributes to let the compiler know that we are in a different environment.&lt;br&gt;
We are in an embedded environment which doesn't have functionalities that the &lt;a href="https://github.com/rust-lang/rust/tree/5b04bbfcbb79ed7325ea2b580458a80d95da6bbb/library/std" rel="noopener noreferrer"&gt;standard library crate&lt;/a&gt; of Rust depends on such as heap allocation APIs, threads, network APIs etc. So we need to add the &lt;code&gt;#[no_std]&lt;/code&gt; attribute at the top. We also need to override the default entry point (&lt;code&gt;fn main()&lt;/code&gt;) using &lt;code&gt;#[no_main]&lt;/code&gt; because we are going to be providing and defining our own entry point to the program. To define our entry point, we'll use the entry attribute macro from the &lt;code&gt;arduino_uno&lt;/code&gt; crate to define a custom entry point. Usually the board crate you use will provide an entry macro to you.&lt;/p&gt;

&lt;p&gt;We then add &lt;code&gt;use&lt;/code&gt; statements to bring the required items in scope from the dependant crates.&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;extern&lt;/span&gt; &lt;span class="k"&gt;crate&lt;/span&gt; &lt;span class="n"&gt;panic_halt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;arduino_uno&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;arduino_uno&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;hal&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;port&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;portb&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;PB5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;arduino_uno&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;hal&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;port&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Notice the &lt;code&gt;panic_halt&lt;/code&gt; crate? We need a panic handler because:&lt;/p&gt;

&lt;p&gt;In the standard library panicking has a defined behavior: it unwinds the stack of the panicking thread, unless the user opted for aborting the program on panics. In programs without standard library, however, the panicking behavior is left undefined. A behavior can be chosen by declaring a #[panic_handler] function. Source: [&lt;a href="https://rust-embedded.github.io/book/start/panicking.html" rel="noopener noreferrer"&gt;embedded rust book&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;Let's move on:&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;#[arduino_uno::entry]&lt;/span&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="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&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;Then we have our &lt;code&gt;main&lt;/code&gt; function annotated with the &lt;code&gt;entry&lt;/code&gt; attribute macro from the &lt;code&gt;arduino_uno&lt;/code&gt; crate. The &lt;code&gt;!&lt;/code&gt; is&lt;br&gt;
the never type which denotes that the function never returns. &lt;/p&gt;

&lt;p&gt;To blink the LED, we only need a few lines of code and set the relevant pin high or low. Let's take a look at the pin diagram of the ATmega328P chip on Uno:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcomponents101.com%2Fsites%2Fdefault%2Ffiles%2Finline-images%2FATMega328P-Arduino-Uno-Pin-Mapping.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcomponents101.com%2Fsites%2Fdefault%2Ffiles%2Finline-images%2FATMega328P-Arduino-Uno-Pin-Mapping.png" alt="ATmega328P chip diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the diagram above, you can notice various pins on the microcontroller. Most microcontrollers, if not all, contain pins that allow the device to both read and write digital values to external circuits. Some of them are categorized as I/O ports.&lt;br&gt;
A port is a group of pins representing a standard interface. These ports are controlled by port registers, which can be thought of as a special byte variable that we can change in our code.&lt;/p&gt;

&lt;p&gt;In case of ATmega328P, we have three port registers to work with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;C – for analogue pins 0 to 5&lt;/li&gt;
&lt;li&gt;D – for digital pins 0 to 7&lt;/li&gt;
&lt;li&gt;B – for digital pins 8 to 13&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The details are explained better here: &lt;a href="https://www.arduino.cc/en/Reference/PortManipulation" rel="noopener noreferrer"&gt;Port Manipulation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you look at the Uno, we have the digital Pin 13 which is connected to the built-in LED. &lt;br&gt;
We need access to the pin in our code in order to manipulate the LED, i.e., set it high or low.&lt;/p&gt;

&lt;p&gt;Let's add more code:&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;#[arduino_uno::entry]&lt;/span&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="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&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;peripherals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;arduino_uno&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Peripherals&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;take&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="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;pins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;arduino_uno&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Pins&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="n"&gt;peripherals&lt;/span&gt;&lt;span class="py"&gt;.PORTB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;peripherals&lt;/span&gt;&lt;span class="py"&gt;.PORTC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;peripherals&lt;/span&gt;&lt;span class="py"&gt;.PORTD&lt;/span&gt;&lt;span class="p"&gt;,&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;led&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pins&lt;/span&gt;&lt;span class="py"&gt;.d13&lt;/span&gt;&lt;span class="nf"&gt;.into_output&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;pins&lt;/span&gt;&lt;span class="py"&gt;.ddr&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="nf"&gt;stutter_blink&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;led&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&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;There's a lot going on in the code above!&lt;/p&gt;

&lt;p&gt;First, we create an instance of &lt;code&gt;Peripheral&lt;/code&gt; which is a list of all peripherals in Uno.&lt;br&gt;
Peripherals are devices that bridge the communication with your chip/cpu with external devices, sensors etc.&lt;br&gt;
Examples of peripherals would be your timers, counters, serial port etc.&lt;br&gt;
An embedded processor interacts with a peripheral device through a set of control and status registers.&lt;/p&gt;

&lt;p&gt;We then create a new &lt;code&gt;Pin&lt;/code&gt; instance passing in the ports from the peripheral instance &lt;code&gt;peripherals&lt;/code&gt;.&lt;br&gt;
We then define a variable &lt;code&gt;led&lt;/code&gt; that will hold the pin number that the LED is connected to. This is created by configuring pin 13 as output pin using the &lt;code&gt;into_output&lt;/code&gt; method of the &lt;code&gt;d13&lt;/code&gt; pin and passing in a mutable reference to our &lt;code&gt;ddr&lt;/code&gt; register.&lt;/p&gt;

&lt;p&gt;DDR register determines if pins on a specific port are inputs or outputs. The DDR register is 8 bits long and each bit corresponds to a pin on that I/O port. For example, the first bit (bit 0) of DDRB will determine if PB0 is an input or output, while the last bit (bit 7) will determine if PB7 is an input or output. I still need to do a bit more reading to fully understand DDR registers.&lt;/p&gt;

&lt;p&gt;Next, we go into a &lt;code&gt;loop {}&lt;/code&gt; and call &lt;code&gt;stutter_blink&lt;/code&gt; function providing a mutable reference to our &lt;code&gt;led&lt;/code&gt; instance&lt;br&gt;
and number of times (&lt;code&gt;25&lt;/code&gt;) that we want to blink.&lt;/p&gt;

&lt;p&gt;Here's our &lt;code&gt;stutter_blink&lt;/code&gt; function definition:&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;stutter_blink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;led&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;PB5&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;times&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;usize&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="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;times&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;i&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.for_each&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;led&lt;/span&gt;&lt;span class="nf"&gt;.toggle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.void_unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nn"&gt;arduino_uno&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;delay_ms&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;u16&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;All we do in stutter_blink is call toggle on led followed by a delay_ms call from the arduino_uno module. This is all done in an iterator. We create a range (0..times) followed by calling map so that we can progressively delay the LED toggle by a noticeable amount. We could have definitely done this using a for loop and that would be more readable, but I wanted to demonstrate that we can use all the high level APIs and abstractions from Rust. We are writing functional code for an embedded systems where the abstractions are zero cost. That's a thing possible only in Rust as far as I know!&lt;/p&gt;

&lt;p&gt;Here's the full code:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// main.rs&lt;/span&gt;

&lt;span class="nd"&gt;#![no_std]&lt;/span&gt;
&lt;span class="nd"&gt;#![no_main]&lt;/span&gt;

&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="k"&gt;crate&lt;/span&gt; &lt;span class="n"&gt;panic_halt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;arduino_uno&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;arduino_uno&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;hal&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;port&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;portb&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;PB5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;arduino_uno&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;hal&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;port&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Output&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;stutter_blink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;led&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;PB5&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;times&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;usize&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="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;times&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;i&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.for_each&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;led&lt;/span&gt;&lt;span class="nf"&gt;.toggle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.void_unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nn"&gt;arduino_uno&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;delay_ms&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;u16&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="nd"&gt;#[arduino_uno::entry]&lt;/span&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="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&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;peripherals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;arduino_uno&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Peripherals&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;take&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="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;pins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;arduino_uno&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Pins&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="n"&gt;peripherals&lt;/span&gt;&lt;span class="py"&gt;.PORTB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;peripherals&lt;/span&gt;&lt;span class="py"&gt;.PORTC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;peripherals&lt;/span&gt;&lt;span class="py"&gt;.PORTD&lt;/span&gt;&lt;span class="p"&gt;,&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;led&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pins&lt;/span&gt;&lt;span class="py"&gt;.d13&lt;/span&gt;&lt;span class="nf"&gt;.into_output&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;pins&lt;/span&gt;&lt;span class="py"&gt;.ddr&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="nf"&gt;stutter_blink&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;led&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&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;Let's try to build this crate:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

cargo build


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If all went fine, you should see an elf file  &lt;code&gt;rust-arduino-blink.elf&lt;/code&gt; generated under  &lt;code&gt;target/avr-atmega328p/debug/&lt;/code&gt; directory. That's the binary we need to flash to our Uno. To flash the elf file, we'll use the &lt;code&gt;avrdude&lt;/code&gt; utility. Let's create a script at the root directory named &lt;code&gt;flash.sh&lt;/code&gt; that does &lt;code&gt;cargo build&lt;/code&gt; followed by flashing it our uno:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="c"&gt;#! /usr/bin/zsh&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"--help"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"-h"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"usage: &lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;path-to-binary.elf&amp;gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"$#"&lt;/span&gt; &lt;span class="nt"&gt;-lt&lt;/span&gt; 1 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt;: Expecting a .elf file"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; creativcoder cargo build
avrdude &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt;/etc/avrdude.conf &lt;span class="nt"&gt;-patmega328p&lt;/span&gt; &lt;span class="nt"&gt;-carduino&lt;/span&gt; &lt;span class="nt"&gt;-P&lt;/span&gt;/dev/ttyACM0 &lt;span class="nt"&gt;-D&lt;/span&gt; &lt;span class="s2"&gt;"-Uflash:w:&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;:e"&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;With that, we can run now run (make sure your Uno is connected via the USB cable):&lt;/p&gt;

&lt;p&gt;&lt;code&gt;./flash.sh target/avr-atmega328p/debug/rust-arduino-blink.elf&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and there you go:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/gFtGud1j5fNAl5yzlu/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/gFtGud1j5fNAl5yzlu/giphy.gif" alt="Rust on arduino"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our first blinking program on Arduino running Rust!&lt;/p&gt;

&lt;p&gt;If you get a permission denied error when accessing &lt;code&gt;/dev/ttyACM0&lt;/code&gt;. You may need to add your user&lt;br&gt;
to a linux user group that has access to the serial interface.&lt;br&gt;
First, we find the group using:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ls -l /dev/ttyACM0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I get the following output on my machine:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;crw-rw---- 1 root uucp 166, 0 Aug 19 03:29 /dev/ttyACM0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To add your username to &lt;code&gt;uucp&lt;/code&gt; group, we run:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo usermod -a -G uucp creativcoder&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Suggestions/comments/corrections most welcome.&lt;/p&gt;

&lt;p&gt;I have several embedded hobby projects in plan, I will be writing about them in future as they progress. Here's the &lt;a href="https://github.com/creativcoder/rust-arduino-blink" rel="noopener noreferrer"&gt;Github&lt;/a&gt; for the code above. &lt;br&gt;
If you want to follow the latest in developement in Rust embedded space, follow the &lt;a href="https://rust-embedded.github.io/blog/newsletter-24/" rel="noopener noreferrer"&gt;embedded rust working group&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Until next time!&lt;/p&gt;

</description>
      <category>rust</category>
      <category>arduino</category>
      <category>uno</category>
      <category>embedded</category>
    </item>
    <item>
      <title>How to add comment support on your Gatsby blog using Github utterances</title>
      <dc:creator>creativcoder</dc:creator>
      <pubDate>Wed, 29 Jul 2020 08:21:58 +0000</pubDate>
      <link>https://dev.to/creativcoder/how-to-add-comment-support-on-your-gatsby-blog-using-github-utterances-423n</link>
      <guid>https://dev.to/creativcoder/how-to-add-comment-support-on-your-gatsby-blog-using-github-utterances-423n</guid>
      <description>&lt;p&gt;Originally posted on my blog: &lt;a href="https://creativcoder.dev/how-to-add-github-utterances-blog"&gt;creativcoder.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This post is about integrating comments support in your blog using a free and open source service.&lt;/p&gt;

&lt;p&gt;Having a way to engage with your audience is probably the next step you can take if your blog is helping others in some way. Back when I had used &lt;a href="https://gohugo.io/"&gt;hugo&lt;/a&gt; as my static site generator, I had used &lt;a href="https://disqus.com/"&gt;Disqus&lt;/a&gt;, which is a comments service/system. But as with ordinary third party services, Disqus is notorious for putting their own ads and can get quite slow. As a fan of open source and code reuse, I knew there had to be some open source comments service out there. After a day of sifting through the interwebs, I found a solution that I think for the time being serves my purpose of engaging with my audience.&lt;/p&gt;

&lt;p&gt;What follows is a quick guide on how to integrate Github's &lt;a href="https://github.com/utterance"&gt;utterances&lt;/a&gt; comments system into your blog. This also became an excuse for me stay updated with all the recent changes in the web dev space, as I've been mostly doing backend for the last two years.&lt;/p&gt;

&lt;p&gt;Utternaces is a lightweight comments widget built on top of Github issues. Some of its highlights are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Open source. 🙌&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No tracking, no ads, always free. 📡&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No lock-in. All data stored in GitHub issues. 🔓&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Styled with Primer, the css toolkit that powers GitHub. 💅&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dark theme. 🌘&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lightweight. Vanilla TypeScript. No font downloads, JavaScript frameworks or polyfills for evergreen browsers. 🐦🌲&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Target audience&lt;/strong&gt;: You know ReactJS, and you probably know better than me and maybe can provide suggestions on how can we improve the integration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;: This comments system only works if your target audience has a Github account, which in majority of cases are developers. As my blog is mostly oriented towards developers, this aligns perfectly with my blog.&lt;/p&gt;




&lt;p&gt;The official guide of &lt;a href="https://utteranc.es/"&gt;utterances&lt;/a&gt; mentions integrating the comments widget on a vanilla HTML website. That won't work for my case as I happen to be running a site that is generated by &lt;a href="https://www.gatsbyjs.org/"&gt;GatsbyJS&lt;/a&gt;, which I think is a really efficient static site generator not only in terms of development experience but also in terms of performance of the generated sites compared to my past experiences with static site generators such as Hugo.&lt;/p&gt;

&lt;p&gt;Gatsby uses React under the hood which meant that I needed to integrate utterances as a &lt;a href="https://reactjs.org/docs/components-and-props.html"&gt;React component&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: I am by no means an expert on react or even a frontend expert, but the following steps&lt;br&gt;
is me just sifting through bunch of documentation pages and tying to cobble them together into&lt;br&gt;
a working solution.&lt;/p&gt;

&lt;p&gt;So here's how I did it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Installing utterances
&lt;/h2&gt;

&lt;p&gt;First, I setup a Github repository (has to be a public repository) that will act&lt;br&gt;
as a placeholder for issues to be created within: &lt;a href="https://github.com/creativcoder/creativcoder.dev-comments"&gt;https://github.com/creativcoder/creativcoder.dev-comments&lt;/a&gt;&lt;br&gt;
This is needed if you have a website that is not running as a Github pages site. If you happen to have your website as a Github repository, you can configure the same repository for utterances.&lt;/p&gt;

&lt;p&gt;Next, we go to: &lt;a href="https://github.com/apps/utterances"&gt;https://github.com/apps/utterances&lt;/a&gt; page. You will see an 'Install' button in green on the right. Clicking that, you will need to provide the repository where you want to install the widget. I chose my comments repository above.&lt;/p&gt;

&lt;p&gt;Post installation, you will be redirected to this &lt;a href="https://utteranc.es/"&gt;page&lt;/a&gt;. In the 'Enabling Utterances' section, we need to place the following script in a div tag (or any container tag) where we want our comment widget to appear:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://utteranc.es/client.js"&lt;/span&gt;
        &lt;span class="na"&gt;repo=&lt;/span&gt;&lt;span class="s"&gt;"[ENTER REPO HERE]"&lt;/span&gt;
        &lt;span class="na"&gt;issue-term=&lt;/span&gt;&lt;span class="s"&gt;"pathname"&lt;/span&gt;
        &lt;span class="na"&gt;theme=&lt;/span&gt;&lt;span class="s"&gt;"github-light"&lt;/span&gt;
        &lt;span class="na"&gt;crossorigin=&lt;/span&gt;&lt;span class="s"&gt;"anonymous"&lt;/span&gt;
        &lt;span class="na"&gt;async&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the script tag above has multiple attributes that can be configured. The important ones to look at are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;repo&lt;/code&gt;: should point to the repository you installed utterances above section.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;issue-term&lt;/code&gt;: how utterances should match the issues with posts on a website. In my case, am using the title of the posts. You can refer to 'Blog Post &amp;lt;-&amp;gt; Issue Mapping' section in &lt;a href="https://utteranc.es/"&gt;https://utteranc.es/&lt;/a&gt; for more details and choose as per your preference.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Integrating the comment widget
&lt;/h2&gt;

&lt;p&gt;Now as I said above, the script needs to be put in a container tag for us to render the comments widget. That translates to having a component in react, within which we'll append this script tag programmatically whenever a blog post page is rendered. This will need to happen conditionally as not all pages are about a blog post page, such as the index page and the about page.&lt;/p&gt;

&lt;p&gt;To have a container for the widget to be created within, I first created a &lt;code&gt;Comment&lt;/code&gt; react component (&lt;a href="https://www.robinwieruch.de/react-function-component"&gt;a functional component&lt;/a&gt;) in &lt;code&gt;components/comment.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// commment.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&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;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&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;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useStaticQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;graphql&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;gatsby&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;Comment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;commentBox&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;(&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;commentBox&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"comments"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Comment&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's a very trivial component. The only thing of intereset here is the &lt;code&gt;commentBox&lt;/code&gt; react ref. &lt;a href="https://reactjs.org/docs/refs-and-the-dom.html#callback-refs"&gt;React Refs&lt;/a&gt; provide a way to access DOM nodes or React elements created within a component's render method. We'll see how that is used later. It's not really recommended to use refs, as they are sort of an escape hatch but since we only have one use case for it here, we should be fine.&lt;/p&gt;

&lt;p&gt;Next, I have a &lt;code&gt;&amp;lt;Posts&amp;gt;&lt;/code&gt; component in my blog which renders each blog post. This is where I want the comment widget to appear at the end of each post. I needed a way to render the &lt;code&gt;Comments&lt;/code&gt; component conditionally. To achieve that, I relied on the &lt;code&gt;excerpt&lt;/code&gt; prop which is &lt;code&gt;true&lt;/code&gt; if the rendered page is an index page, where only an excerpt of all blog posts are shown. In other cases it's set to &lt;code&gt;false&lt;/code&gt;. We can use that to conditionally render the &lt;code&gt;Comments&lt;/code&gt; component like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/posts.js&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;excerpt&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&amp;lt;/&amp;gt;:&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Comment&lt;/span&gt; &lt;span class="na"&gt;commentBox&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;commentBox&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's the usual ternary operator. The &lt;code&gt;&amp;lt;&amp;gt;&amp;lt;/&amp;gt;&lt;/code&gt; syntax are &lt;a href="https://reactjs.org/docs/fragments.html"&gt;fragments&lt;/a&gt; in react, which is empty in the true branch as we only want to render the widget when the user in on the blog post page. We also see that the comment widget has a &lt;code&gt;commentBox&lt;/code&gt; prop being passed. This is how we gain access to the &lt;code&gt;Comment&lt;/code&gt; component for use within the &lt;code&gt;Posts&lt;/code&gt; component. We'll use this ref to append the comment script tag.&lt;/p&gt;

&lt;p&gt;Back in my &lt;code&gt;Posts&lt;/code&gt; component, I create a ref that was attached to the &lt;code&gt;commentBox&lt;/code&gt; prop on &lt;code&gt;Comment&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/post.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;commentBox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createRef&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, I use the &lt;code&gt;useEffect&lt;/code&gt; hook to add the script tag to the &lt;code&gt;Comment&lt;/code&gt; component via the ref:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;commentBox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createRef&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&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;const&lt;/span&gt; &lt;span class="nx"&gt;scriptEl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;script&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;scriptEl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="nx"&gt;scriptEl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://utteranc.es/client.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="nx"&gt;scriptEl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;repo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;creativcoder/creativcoder.dev-comments&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;scriptEl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;issue-term&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;scriptEl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utterances&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;scriptEl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;theme&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;github-light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;scriptEl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;crossorigin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;anonymous&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;commentBox&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;commentBox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;commentBox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scriptEl&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Error adding utterances comments on: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;commentBox&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="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;The code in &lt;code&gt;useEffect&lt;/code&gt; will run everytime a &lt;code&gt;Post&lt;/code&gt; component is rendered which will then append the comment widget to each blog post page. You can see that set the same script attributes are being added but with javascript. We then finally append it to the &lt;code&gt;commentBox&lt;/code&gt; ref via its &lt;code&gt;current&lt;/code&gt; property which is active when it is rendered.&lt;/p&gt;

&lt;p&gt;With that done, I did just did a &lt;code&gt;yarn deploy&lt;/code&gt; and what you see below is our shiny new comment widget 👇.&lt;br&gt;
Hope you find this post helpful. Let me know if you have any issues setting it up in the comments below.&lt;/p&gt;

&lt;p&gt;Until next time!&lt;/p&gt;

</description>
      <category>gatsby</category>
      <category>blog</category>
      <category>comments</category>
      <category>utterances</category>
    </item>
  </channel>
</rss>
