<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
  <atom:link href="https://micaelnussbaumer.com/feed.xml" rel="self" type="application/rss+xml" />
  <title>micaelnussbaumer</title>
  <link>https://micaelnussbaumer.com</link>
  <description>Personal Blog &amp; Site</description>
  <language>en-us</language>
  <generator>Tableau v0.30.0</generator>
    <item>
       <title>What is reality?</title>
       <link>https://micaelnussbaumer.com/posts/what-is-reality</link>
       <pubDate>Tue, 17 Mar 2026 00:00:00 +07</pubDate>
       <guid>https://micaelnussbaumer.com/posts/what-is-reality</guid>
       <description><![CDATA[ <p>Yes, it's not like we won't be talking about it but it's a bit of a clickbait title. Have you seen <code>&quot;Inception&quot;</code> the movie? The one starring Leonardo DiCaprio. One thing that caught my attention was that all characters had a &quot;token&quot;, a physical &quot;artefact&quot;, they could use to discern if they were inside a dream or in the real &quot;reality&quot; itself.</p>
<p>In case of Leonardo's character he has a spinning top, that has a very peculiar property, when it's spun in a dream it never stops spinning, while obviously in the real &quot;reality&quot; due to the laws of physics it eventually stops spinning. This is sort of a &quot;Deus Ex Machina&quot; for the history but it plays really well and doesn't feel like one because the effect only becomes &quot;supernatural&quot; when its owner is dreaming, so in fact, the artifact doesn't have itself any magical property.</p>
<p>In terms of story though, if you squint, this is like a magical sword in a fantasy movie, or a special inhuman ability someone has in some other kind of story.</p>
<p>It's the interplay of that supposed property of the &quot;token&quot; with the &quot;dream&quot; universe of the movie that allows major plot progressions, and in a way lead, perhaps, to the most poignant question that the movie raises, when in the ending scene we see Leonardo's character in his supposed real home, we hear the voices of his children in the background, signifying they're playing outside, it has an idillic mountain/camp house ambience to the scene, yet at the same time, the spinning top is spinning on top of the table. The scene lingers a bit and cuts to the end. It's that lingering that makes it the most poignant scene in my opinion, because it kinda feels when you're watching just before it cuts that the spin top was already spinning a bit more than what would feel normal, and then it cuts and you don't have your answer. So without the spinning top you can't know if the character is eventually in &quot;real&quot; life and found the happiness with his family - that he continuously says is one of the motivations throughout the movie - or if the character is in a dream, addicted to a certain dream and is returning to it, and if so if either he's there voluntarily or he's stuck and doesn't know.</p>
<p>There's that final tension. I find some parallels to what our experiences in this reality, whatever it might be, can ultimately reveal us about reality itself.</p>
<p>In a way you can't really know if you're in a materialistic first reality, a conscious first reality, a simulation or a God made reality - that is functionally equivalent to a simulation, in the sense that for you, as the subjective experiencer of reality, you wouldn't be able to tell a simulation from a God made reality because they can look like exactly the same.</p>
<p>If I think about it, how could I know I'm in the &quot;ultimate&quot; reality, the real one and not in a dream, or a simulation (all those are functionally equivalent, so I'm going to refer to them as simulation from now on).
I need either something internal or external to this reality to show me that, or I need to have noticed or understood some detail that would indicate so.
Because how could you test it? And even if you were to be shown, or understood it by yoursel, or somehow woke up, got enlightened, whatever, then what? How could you know that you were not in another simulation or dream? And this is basically the problem. &quot;We&quot; don't have a magical spinning top and &quot;we&quot; don't know what &quot;we&quot; don't know.</p>
<p>So let's see the different types of philosophies that we can think of coming out of these different approaches we could take.</p>
<p>A materialistic first reality. This is what most atheists, marxists, utilitarians, etc, ascribe. They say there's nothing else than matter that happens to become conscious by chance and from there we get here through a sort of evolution. Notice here that when I say matter, because you are starting without consciouness, this can only be rocks, minerals, liquids? Not sure there can be liquids without life, but anyway it's this type of matter, not matter like tree bark, or flesh, because those can't exist without consciousness. This branch doesn't provide a framework for before, or after, sure, some theories might present but they're far from being even significant in gathered support for their views and not proved (some not provable with what we know and tools we have right now).</p>
<p>So the biggest gap in this philosophy, to me, is how do we go from unconscious matter to consciousness. I like to imagine it like this. Have you seen a lightning storm? One that goes for a while? Like those lightnings they occurr in that situation, in that context, atmospheric, temperature, etc, but they're fickle. The lightnings strike and disappear, the charge just dissipates into the material world. The conditions change, the lightning no longer strikes. So how could electricity be stored in matter in a way that would give rise to biological beings with consciousness?</p>
<p>It seems that a vessel that could contain the current in order to use it for consciousness has to be &quot;designed&quot; before (not strictly in the sense of intelligent design, just that it has to have come up somehow before) consciousness arises in the material world, because otherwise, how would it come to be? But then how would life get to that design without life a-priori, just from rocks and thunder? A rock charged with electricity wouldn't be able to give rise to intelligence RANDOMLY (yes, silicon indeed can be charged and &quot;think&quot;, but it has to be excruciatingly designed at a scale beyond human sight, and it still doesn't evolve into a biological cell that has a self programmed will - I'm not even saying we can't get there, but I'm really doubtful that such sequence could happen randomly in a total material world).</p>
<p>The biggest problem is that without will/consciousness, that are immaterial properties, there's no reason for life to come into existance. Why wouldn't the universe be just rocks floating in space?
Even if we assume that because it has no beginning and no end it's infinite, and by being so it guarantees that all possible combinations of matter will occurr at some point, and as such can be assumed to have occurred and we can use it as assumed condition, even if a complex structure by pure random chance, that would be 2.225074e-308 but we're assuming the universe is infinite so we can assume this will too happen sometime along the way to infinity, and as such we can assume that that point is in fact now (or like some billion years ago), and was able to hold electricity in a contained way, why would that lead to consciousness? It seems that SOME directed consciousness needs to be there prior to enable a proper vessel capable of using that energy for consciousness to emerge. A bit of a snake eating its tail, or as we say in Portuguese, pescadinha de rabo na boca (hake with the ass/tail in its mouth) situation.</p>
<p>That's my biggest gripe with it, it can't explain anything of the mistery. It also gave rise - until quantum physics started cementing themselves - to many branches of determinism. Like the thought that all humans are the same at birth (beyond the &quot;rights&quot;), just separated by class, hence material conditions, and that they're a white page that then can be culturally and symbolically programmed into an &quot;higher&quot; man - very common in all forms of socialism, be it national or international. Although it is clear that the cultural, material, social dimensions have a direct and significant impact on the adult human one becomes, it's not in that way. You can't make an assembly line. It doesn't mean that it can't provide philosophical advancements, or only has bad repercussions. As the saying goes, even a broken clock is right twice a day, and more than that, if you are using right and wrong to describe theories that means there's a point that should be the correct, which consequently also means that if you start deviating from that point for any reason, then usually the course to correct that will be to temporarly go in the wrong direction.</p>
<p>Variations, and they go back to the sperm and egg that eventually agree to fuse, result in individuals that have underlying &quot;hardware&quot; different between themselves. So while you can create a &quot;program&quot;, your programming doesn't guarantee a deterministic result. For instance, imagine an overly harsh, militaristic, homophobic father. He makes it all clear all the times yet, sometimes, the son comes out gay. Or imagine a school, you teach a subject, the professor has an inclination, can't work around the bias, yet, even then, different people will react differently to the things he will be talking about, creating different interpretations. Now, in both cases, they all can exhibit and behave as if they weren't, and agreed, respectively, but their inner monologues can also be different from what they &quot;signal&quot; publicly.</p>
<p>Obviously, if used to an extensive extent and well done, you can almost &quot;create a new man&quot;, the thing is that it never really changes, it just puts on a facade according to the programming. But still, eventually, these systems, even those that manage that, seem to falter and fall. It's the nature of the human that never really changes. With the advent of quantum physics the classical model of physics stopped being the only way to describe reality, in fact, it became obvious that it's not total in any way and only coincidentally very useful, so determinism suffered a blow, but it recouped by integrating quantum physics' randomness, and allowing free-will. Materialism on the other hand has a bigger problem in my opinion because how does it bridge that gap between the materiality described and the apparent immateriality of certain aspects of reality.</p>
<p>If we look at a conscious first reality, on the other hand, it's immediately out of reach from a pure physics description, since we can't even define consciousness in any relevant non-ambiguous form. A conscious first reality allows many more easier answers - because they can't be tested as of now, only theorised - such as, if consciousness is in fact the underlying basis of reality, solving how do we get to conscious entities is pretty straightforward logically. The consciousness &quot;field&quot; gives rise itself to vessels that can contain consciousness, pretty much as the seed of a tree knows what the fruit will be and how to get there. In the end, the fruit bears the seed right? As you see, it's pretty straightforward and in case consciousness is the basis of reality it would make intuitive sense that it was so that we came to be. Variations of this chain of thought are gaya theories, cosmic universalism, etc. Again, if consciousness is the basis then the universe evolution is a manifestation of the will of that abstract consciousness, and the coming into existence of Earth itself too, and the evolution of life, etc. Similar to gaya (Earth) theories, where it's all the same thing and interconnected system that manifests in heterogeneous looking realities while sharing the same universal basis. In my opinion, such a view is ultimately indistinguishable (to the experiencer) from a God made reality or a simulation, although its conceptual frameworks are different.</p>
<p>Now lets turn our attention to the next possibility, a God made reality. This branch of thinking obviously pressuposes the existence of a God that is above all. This is needed because how can you go from nothing to something? And if not, if everything, or something is always there, how can that be, how and why does it sustain itself eternally? Ĩf in your mind for some reason that second question leads to a nonsensical answer - the reason being you think there needs to always have a start and an end, and you don't believe (logic, personal experience, wtv) that the world is first and foremost material (because you had some experience that leads you to believe it's metaphysical due to syncronicities or wtv), then your only option is to believe in God, in some way. It's also why perhaps most of the initial advancements in science all started in religious contexts, it's very probable even that the experience of natural phenomena that seems to follow a logical reason strenghtens the belief in some logical order that precedes everything - it seems we can understand even parts of the invisible and all sorts of things beyond our natural abilities, and that those parts seem to be in their own way and context consistent (in the logical sense).</p>
<p>When we look at several scientists many do affirm a belief in God, and we can probably look at their unwavering dedication (sometimes ungratefully treated, not rewarded, etc) as the side effect of their belief in a logical God, because if God is logical then it must follow that reality, specially because he created it, is logical too, and if we're created in his image then the understanding of those logical connections should be in reach. At the same time, depending on how many people you would consider idiot, it could be used as an argument against the idea that God created us in his image, since there would be so many idiots that it would have to mean that God was in some fundamental level idiot too. But that is kind of elided by the argument of free will.</p>
<p>Going back to scientists. I'm not saying that the story of the apple falling is what gave Newton the idea for gravity, but I'm pretty sure we all have been, either directly or as observers, in situations where someone says &quot;na, this must mean this, because of this and that&quot;, or &quot;this isn't really possible in any reasonable way&quot; and then someone goes &quot;no, it's because this and that and you can see here and there&quot;, or &quot;wait, but couldn't we do this and that, and then we get that? It seems like it should work&quot;. Right? People look at things, sometimes the same exact thing and they don't have the same ideas, associations, connections, feelings, being triggered. Taking the story of the apple falling, we could ask, how many people in the whole history of humanity have seen apples falling? So the question shouldn't be &quot;If a tree falls in a forest and no one is around to hear it, does it make a sound?&quot;, it should be, &quot;If a tree falls in front of you do you even see it?&quot;.</p>
<p>God has to somehow be bigger (in a energetic, intellect and informational sense) than the universe he's creating, otherwise how could he bring it to existence? More specifically, how could that entity be omniscient? If we know that each manifest bit of reality can't be reduced informationally to 0, otherwise it ceases to have any distinguishing feature from the remaining bits, and if it seems that the universe is infinite, for a conscious entity to be omniscient of every bit of it, it would need to be infinitesimally bigger than the universe it's omniscient about, otherwise where would the information upon which the omniscience is based exist? So we have to assume that if God created it, He has to exist beyond that which he created, and due to his other qualities, we must assume those other properties (e.g.: if God is omniscient about an infinite universe, he must be infinite Himself to accommodate all the quanta of information required to do any meaningful action that has any semblance of justice, morality and/or compassion).</p>
<p>It could also be that the things that matter are in fact invisible and in much less abundance and the exuberance of life is but mirrors, so that God would only need to keep track of a very small subset of reality to keep its supposed attributes of justice, fairness. Obviously, there could be other ways, but these are those that I can think of that make any sense. God could obviously be not definable or comprehensible by the combination of my own material body and mind.</p>
<p>The same with relation to other gods, if there can be many gods and they can each create &quot;realms&quot; totally independent from each other, then this is less of a &quot;God made reality&quot;, an instead the direct equivalent of a simulation, since each &quot;realm&quot; (the combination of people believing and some sort of organisative structure) will have its own rules according to who created it or rules it. If that is so then it shouldn't be that we have a universal baseline of what we deem moral, just and fair, that has been trending to the same direction across the whole world, mostly due to dialetics, war and commerce. It should be that each reality of each God would be, to have any semblance of fairness, rewarding of the qualities those Gods desire. So multiple competing Gods doesn't seem to lead towards that universalism either, because you can't be fair if you accept different measures of moral, justice and fairness. That's why for a God made reality to make sense you need monotheism in my view. The hindus thread sort of a mixed way, but they get a bit lost on the definitions in my opinion.</p>
<p>“Whence this creation has arisen — perhaps it formed itself, or perhaps it did not. The One who looks down on it, in the highest heaven, only He knows — or perhaps He does not know.”</p>
<p>In the end they seem to not conclude anything about how or who created reality, which is a very sensible position but makes it so that it's not really believing in a God made reality, just not refusing that possibility, hence why I say it's sort of a mixed way.</p>
<p>In Christianity and other monotheistic religions they argument that God precedes reality, and it's God himself that designs reality to his will, including yourself.</p>
<p>Because this isn't a particular essay on each of these branches of ideas, but instead an attempt to showcase why they come to exist and how they mold and format our understanding, our ways of life, our choices, otherwise how could it fit in a blog post, there's probably entire libraries written about these topics, let's move to the simulation reality.</p>
<p>Like I mentioned before, as simulation I will treat both in the technical sense and the metaphorical sense, both the possibility of living in a software based simulation and that of living in an hardware based one, both are the same for our purposes because they would look exactly the same to you, unless you had some spinning top to help you discern (I guess in the hardware one not even that). The same with like, ideas of an alien seeding, or extraterrestrial meddling with earth bound creatures, spiritually, genetically or whatever, all those, render the same situation, for you, e.g.: if you were seeded by aliens but you think you have evolved naturally from apes, or that God created you, it would be equivalent to living in a simulation, although there's no intrinsic desire to &quot;simulate&quot; anything.</p>
<p>It's interesting to also think, as purely speculative paths, that if it was some sort of extra-terrestrial seeding or meddling, the end result, besides being technically a simulation, also poses those other questions that a pure software simulation hypothesis would pose, how do you know when it's the &quot;ultimate&quot; reality, the one that is not simulated? But instead in this case it is, how do you know who is the originary extraterrestrial &quot;source&quot;, would they be the originals? Would they have also been seeded? And if we somehow came to the conclusion they're the originals how would that elucidate us about the nature of reality? How did they come to be, how did consciousness arise in them too?</p>
<p>That's an important point. In this chain of thought, given what we know about the human body, reality, mind, we can imagine a technical situation or context where we would be experiencing a &quot;simulation&quot;. If we can have Neura links messing around directly with memories, if we can figure a way to manipulate those memories directly, we could create a totally simulated experience, that anybody under that experience wouldn't be able to tell apart from their everyday experience, at least while in it. Right? So one of the things that messes this chain of thought is the &quot;why?&quot;. Because depending on the why, or even if you can find one for your view, changes completely the ramifications of your experience of the simulation. And without a why there's really no reason.</p>
<p>For instance in &quot;The Matrix&quot;, the reason why is that the matrix uses human for storing energy, many people come out saying it doesn't make sense, energetically, to use humans as batteries. It's a &quot;Deus Ex Machina&quot; nonetheless, anyway, there's a whole bunch of ways of justifying machines needing full-body developed humans with a functioning mind, so that is not really a problem, a bit of suspension of disbelief is normal when watching a movie.</p>
<p>Why would a simulation even be created? Well, we could think of some reason, we already kinda do it in smaller scales, even with humans, we try forms of organisation for different institutions that are essentially simulations, even in our everyday life I'm sure you have also done it. Like if you ever tested a friend, a partner, a person, your child, on their true intents, or how they behave in a given situation or context, then we can, technically, call that a simulation. You've simulated an occurrence, or architected it, to see how something would play out. That's essentially a simulation, if the people participating in it don't know, it's even closer conceptually to the spirit of &quot;reality as a simulation&quot; that you can't be aware of.</p>
<p>So the first &quot;why?&quot; could be simply as a simulation to examine future behaviour? Imagine, an advanced species that has found a way to simulate their systems and uses it to test things and take decisions. For instance it might test if a certain kind of DNA leads to a type of person or another, and if it leads to the desired type of person, then they proceed to use that DNA fragment to generate the next generation of their own species, or to-be-parents choose from a pool of their own eggs/sperm possibilities and play it out in a simulation that runs in 3 secs. Lets assume for the sake of discussion that this makes sense. If this &quot;civilization&quot; was looking for people who were extremely agressive, because it's totalitary, utiliarian, military species, then perhaps the test is if you are courageous and ruthless enough to rise above anything and anyone. The further you do the better the DNA strip scoring.</p>
<p>On the other hand, if this &quot;civilization&quot; was looking for the type of person that is peaceful, looks to help others, doesn't mistreat others, then succeeding in that kind of &quot;simulation&quot;, where the &quot;why&quot; is that, means you would end up something like a Christian, or a Buddhist, or some gurus of different traditions,- if you look at it from the point of view of the All-Knowing Father, the Eye in the Sky, Karma, they would be pretty interchangeable metaphorically with a simulation that is being run with an evaluatory purpose.</p>
<p>Why is this theory important to at least consider? Because it's sort of feasible. You could be in a simulation, there's plenty of whys and technically it looks definitively possible. Why is it important to not be consumed by it? Exactly because you could never know without external intervention if you were or not, even if this one you could be sure, the same problems will just repeat one level above, and then another, and then another.</p>
<p>If this is so this tells you you should not linger on it, since it's not up to you to discern. If it's a simulation all bets are off. You remember that apparition of whatever you had, and took you on a long journey through X and becoming Y. Well, it was simulated. You see? There's no possible escape. This doesn't mean though that you shouldn't be aware of its possibility.</p>
<p>Going back to our topic at hand, it's impossible to know without direct intervention if we are in a virtual, God-made, or natural reality, and if we have an intuition that it isn't random, then we are bound to two of those possibilities and we can't discern between them (without a noticeable crack in the reality that would be somehow discernible and that we would be able to understand, or without intervention of some external or magical entity/power/object).</p>
<p>There's some details that might indicate a virtual or simulated reality. The way reality behaves in terms of measurements would be consistent with a system that is trying to optimize space and processing power. The same for an almost infinite but almost empty universe. It can look vast beyond comprehension but computationally, because it's mostly empty with inert and unconscious matter that follows pretty simple simulations - simple in the sense that it probably would cost less power to process all the info in 99% of the universe, the inert part of it, than it would to calculate fully one human life. Perhaps.</p>
<p>The, what appears to be, fact that certain properties of reality can only be known one at time, in that we can't really measure those properties at the same time, or the probabilistic fields used to calculate things at microscopic scale - this would be appropriate in what we call, in programming, a lazy iteration, meaning, the values are not calculated until someone looks at them, or something that is either conscious or is in the conscious mind of some conscious being (perhaps only human, who knows), interacts with it in any relevant matter. When this happens the details unfold, but until then no additional energy had to be used to calculate/process any of those particular things at that level of detail because everything else can be approximated statistically from a known base.</p>
<p>It's only when consciousness interacts that there's this explosion of possibilities. Now, it's important to understand that this could also be a natural world and those &quot;glitches&quot; are in fact artifacts of our methodologies, tools and understading. Given that we know that nature doesn't seem to waste energy, and goes for the path of least resistance, we could imagine a natural world that assumes such a configuration because it's the most efficient, in whatever relevant manners of efficiency ultimately matter. In such a natural world consciousness could still be part of the fabric of reality, which would force matter to have &quot;crevices&quot; where consciousness could plug itself, making this natural reality compatible with a simu-God-looking reality and at the same time with most modern understanding of reality at that level, where in fact it appears that matter is less solid than thought and where it behaves as if influenced by non-matter factors.</p>
<p>Now let's change to more practical, mundane things. Lets say you live on the West, is the democracy you live under really a democracy? Or has it been captured at different levels, not even only national, by burocratic groups managing the allocation of public money? In fact, it all seems to be democratic. You have elections, numbers come, you can see tendencies, bias, clear favouring, undemocratic treatment, both institutional and non-institutional, but ultimately, when a shift starts to appear, it ends usually being able to fight through the institutionalised corruption and capture. Ultimately it's mostly an illusion too. If you were to think through, yes, indeed, depending on the country and context, individuals that are the front-face of governments, or governmental positions, many times aren't those who are really in control. Many are just the figures that need to go into the cutboard shapes.</p>
<p>They pass laws that they were told to, negotiate towards something with personal and ulterior motives, then hold positions in concertated spots that allow them to cover each other's asses, steal money directly from projects, funds, and budgets that should have gone to other things, get together in their best suits and dresses and commemorate democracy while all their countries can't even fuck to maintenance levels, highest consumers of most hard recreational drugs by several miles, alcohol probably too, same for antidepressants, where public services, infrastructure, governance, locally, become everyday more enshittified, but then the &quot;overlay&quot; institutions put on this makeup of professionalism.</p>
<p>It's covid, millions spent in shit, but you put your mask on didn't you little piggy? Even if it's fake you're still the piggy-mor, the real trampa, never forget when you look in the mirror. In 6 months or so there were already contagion contact apps, a few more, biometric vaccination passports going to be implemented in Europe. 30 years they still can't trace where millions end up, but for your uniquely associated government issued wallet, oh baby, it even has GPS real time tracking. All paid with your money thank you.</p>
<p>You see the motor of the economic growth was drinking pig oil, while paying champagne to themselves, so most evolved, so above the other ignoramus peoples, hogs, that managed to loose a leading market, where they had like 50 years of advance, being inside or having access to the richest markets in the world, tying the whole industry and those adjacent in weak international positions, while, not without a reason but still, calling others &quot;PIIGS&quot;. The problem is the red crossings. It's easy to prop your whole economy when you're buying at a discount from an enemy that has just invaded a neighbouring country. And you keep it going for years. Squeaky clean.</p>
<p>Then look at the services, I'm not sure how it's in other countries but I hear and see examples that are in some cases even worse, I don't know if to laugh or cry.
Civil servants, or public workers in socialist-tending economies (or others that manifest the same through nepotism, and such), because they're overly protected by the state (or nepotism, etc) have a for life tenure coming with it, for as longs as you just play the right game. You can't be fired for anything other than egregious faults for the most part or cabinet changes - but those are politicians, even though it mixes, here I'm talking mostly about the unchanging mass.</p>
<p>So people start treating those positions like they're something they're owed and that they own, like they somehow have the right to put their own emotions, opinions or will above the processes and law, transforming the position into their own little dick serfdoms.</p>
<p>For instance you might find out after you go get the previous contracts for your new rental's electricity and water that none of them match the real address registered in your contract. So you now have 3 addresses that don't match, the canonical one, the one from the property registration reflects an old address that no longer exists because the land was re-ordained and given new names and numbers, somehow though, because the budgets come but the outcomes not, there was no updating of the underlying records, who needs that, so the others have different addresses, besides the specific things different between each. It starts immediately here. This irregularity now seeps throughout everything it touches. It can create all sort of problematic situations that are the result of such systems. It's great to hide things too, because nothing is connectable, and it also means that if the State needs data to feed its decisions it's all a shithole.</p>
<p>Then you go, want to register a company, there's no calculator that can give you exactly what you're going to pay in taxes, and when, and how, no, you need to pay someone, to then not be able to tell you either, but you need to pay this person (the accountant) anyway. But the question here is, would you go to a restaurant, buy groceries in a store, or whatever, if that place told you, &quot;know what? now you came inside you need to pick something, take it, and we'll tell you how much it is after and you can't return what you choose&quot;. Then add to this that you're forced by law to have this paperwork done, because there's no other possible way right. Really impossible to have a program that calculates immediately everything. Where would they steal from then?</p>
<p>Then they behave against the law themselves, in the regional counters, company counters, no responsibility, one says something, you waste one day fulfilling it, to then arrive at the other place, at your expense, and the person refuses to attend you, but accepts the money it would cost, and then you find out after a year that those things were never put forward because the change they should have triggered wasn't, and you only notice when you receive the yearly papers. No one responsible. This whore probably has worked there for 30 years, by the look of that diarrhea skin, going to work there until retired then retire with it all paid by others, the only reason she has a job is because probably sucked enough cocks or is the wife of some corrupt pig.</p>
<p>For you to understand the reality matrix you need to understand other things that aren't very pleasant. You know that saying, it's hard for a pig to understand he's a pig if his food comes from him not knowing he's a pig? You can put the cows smiling on the milk packets, tell your little children how it's all needed and for them while it's an excuse for you to keep being the same pig you always were. Your lies will catch up to you. Thank God.</p>
<p>You see in socialist rethoric, they always talk about how the struggle is in the name of the worker, how &quot;work according to each one's capacity&quot;, and other pig lies. What they really mean by work according to each one's capacity is, we're going to be the genius bosses and you'll do whatever the fuck I want.
You can see for instance the way the matrix operates in reality, through very subtle things. If you play the game of Civilization you'll see that one of the forms of government you can choose is &quot;Communism&quot;. The game is a resource game, so you need to manage resources, and under &quot;Communism&quot; you get a whole lot of perks derived from the fairytale of &quot;planned&quot; economies. Your fields in the game start producing much more because the magic of communism automatically multiplies the outputs due to the genius level of organisation.</p>
<p>The reality is that the real genius communists in genius communist countries triggered several deadly hungers due to food shortages in a combination of retarded ideas, complete lack of organisational skills and systems coupled with endemic corruption. The genius in USSR Ukraine was developing out of the ass theories that were latter projected to have hampered significantly the agricultural output in several provinces of the USSR, one of the genius ideas was if and when the cultivars were rotting, to place them under the earth, as that would do some fairy tale magic thing. In reality as it was rotting, protecting the rotting thing from the cold and sun by covering it, with a layer of dirt, ended up speeding the rotting process manifold.</p>
<p>In China Mao manages to also kill a few and gave show of his enormous agricultural genius several times. One was the 4 Pests campaign, where he decided that to solve the problem of pests taking bites out of the perfect Communist productivity they needed to erradicate them completely, so they launched 4 campaings targeting rats, flies, mosquitoes and sparrows. The extermination of sparrows led to a several ecological imbalance that resulted, in the lowest numbers projected, in 15 million dead in 2 years of starvation, with some numbers going as high as 55 million.</p>
<p>This idiot was also the one who said some nice things about buddhism, the little pig, but now the CCP understood that Buddhism has more soft power than all their pig politburo together, and now is asking the Dalai Lama to re-incarnate in China. Imagine what kind of fucking retard you have to be. Then the real leap forward. After loans from USSR, help from other countries, a country of hundreds of millions at the fingertips and still these retards couldn't make it work. Then it worked when some Hong Kong chinese got the green light to build the first free economic zone of China, after the CCP had rejected it previously. But of course, the incompetence can only go so far because after a while heads will roll, so they went ahead and finally gave green light.</p>
<p>The rest is not history, because even the following growth was all dictated by economic partners that were capitalistic, with transfer of technology mostly coming from capitalist countries. China is now the country which produces more billionaires per year. And these guys do a parade for Mao. How do you want me to call you? Why would I want to be part of that or my society turned into something like that? Even faker than what it already is. So you can go on electric buses to your 9-5 to then eat a pre-cooked meal served by robots and keep your pig behaviours because now there's not even scarcity to contend for? Raising more little pigs that behave like individual cancer cells.</p>
<p>Then you look at Cuba, since 1958 under the Castros. Longer than many family royal interludes. But it's all for the people. Obviously that island is probably cursed because everywhere else on earth but communist countries, even in fucking siberia, people manage to create agriculture outputs in enough quantity to not need food stamps to distribute it. People living in houses that look like they were built on the first wave of Conquistadores. And the embargo doesn't count. For many of these years Cuba had direct MONETARY assitance from the USSR in EXCESS of the estimated losses due to the embargo - and this  was done so that the socialist solidarity against the capitalist rotten individualism was in full blown display. So they didn't really have any embargo in the real sense of the word. The USSR had an almost as extensive area of influence as the USA and Cuba was receiving money in excess of what they would be able to produce naturally.</p>
<p>But what did they do with that money? No one knows. Ta ta ta ta ra ra ra ta ta ra ra.</p>
<p>In Bangladesh they had a few millions to fix a central area of Dhaka, the millions disappeared, not a single improvement done, people living worse than pets in the west, but then the fault is of the West, obviously, not of those burka pigs.</p>
<p>Once I went surfing in Bali a retarded local went out at the same time and shouted to me &quot;Go back to your country&quot;. I'm fine if people don't want foreigneirs in their country. But this fuck head is there surfing because foreigners came to that island and set that style of life. What that retarded deserved is to go back 60 years and go work the rice fields for his life and then sell his little daughters to get fucked to make money to pass by. And in this case it's even more egregious, these pigs coming from indonesia, with their muslim pig habits, they go there and set bombs and kill not only foreigners but the true locals, want to impose their rules over others that had been there for millenia. Can you imagine what kind of people this is?</p>
<p>Go see what this beautiful people did to the people of Timor-Lest when they decided to keep their independence. Go see. Fucking pigs. And then they go around talking about others with their pig mouths still dripping shit.</p>
<p>Go see Venezuela, where quality of life was skyrocketing before and see what it turned into. An open whore house and drug production country. Almost 8 million people got out just under Maduro's rule. A whole ton of others live, again, worse than some people would allow their pets to live in the &quot;West&quot;. But the fault is of the West, not their pig development plans. Being the drug lab for Europe and Spain more specifically. You never wondered? Why these countries manage to live from what is essentially a plant that mixed with diesel, and grinded goes for at least 50€ a gram in Europe. You never? And why amphetamines for instance there's no traffic into Europe? Because they have their own labs in the Netherlands.</p>
<p>This is why you never catch drug dealers. It's always some retarded looking fuck that lives with 2 girls, 2 guys, a dog, and a cat, in a 2 bedroom flat that is the great mind behind some hundred million a container pop trip crossing several jurisdictions. Of course you can't have cameras on the docks, what non-sense is that, or you know automated x-ray machines, public records, etc. In all streets except the politicians homes and institutions, a camera per sqm, where it matters, ooopsie, forgotsy.</p>
<p>In a way it's funny that it's the fact that they're so incompetent that got them caught in all sorts of surveillance apparatus. That's what you get when you're only worrying about filling your filthy mouth like a pig. The sad part of this is the ones that have a hold of that information might not be much cleaner.</p>
<p>Do you ever wonder why laws are made the way they are? For instance prostitution. Isn't it funny that all these feminist parties, and so-called &quot;socio-democratic&quot; societies, all illegalize prostitution? I would say that with exception of women born/married to powerful individual/families the only women throughout history to hold any real amount of power were whores.</p>
<p>But this no good for business. So they make it illegal for a women to decide if she wants to charge money for a blowjob. To protect them. How funny it's then to find out whore houses everywhere, attended by politicians, cops, the guy from the barbershop, everyone. Then countries like Sweden, so worried about the little ones and prostitution, that it's completely illegal, you can go to prison for it, and because it's a cunt society you just need one retarded cunt to go to the police to get you in a whole problema.</p>
<p>On the other hand illegal undocumented immigration? Couples with several undocummented children? All covered from toe to head, no documents, from a culture that has contracts to fuck little children. That's all good. We're very humanistic, philosophical diarrheas. Let's not do anything about illegal immigration, which is the single-most linked factor to children-trafficking sex networks. Hmmm, how interesting. They probably want to teach them how to play LEGO after some good swedish meatballs.</p>
<p>Then the pervasive lies. Every country does the same but I know some examples in first hand from Portugal. I came to the conclusion that the reason they call names such as &quot;Dark Ages&quot;, &quot;Fascism&quot;, and talk so little about them is so that the incompetence isn't more visible. In Portugal they renamed the &quot;Salazar Bridge&quot; (built during and in honor or Oliveira Salazar the prime-minister during the Estado Novo dictatorship) to &quot;25th April Bridge&quot; (in honor of the Carnation Revolution that ended Estado Novo). So people might think that the existance of that bridge has anything to do with the socialist/communist movement of the time and consequent socialist/commie governments. But it hasn't.</p>
<p>Then when you ask about why Portugal stagnated for so long and still is in the tail of Europe, they talk about the costs of modernising, that they implemented public education, and so on so on, that's why the moneys goes and the country doesn't.
But when you look more closely - and I just want to leave on thing clear, I'm not in favour of a fear based dictatorship, fascist or not, even though Estado Novo wasn't fascist at all, and I don't think that &quot;Futebol Fado e Fátima&quot; is where I wanna be living either - during the &quot;Estado Novo&quot; they managed to raise the literacy levels to about 46/48%. This is almost 50%. We also have to take into account that the pivotal work is always the most difficult, because it involves setting up all the infrastructure, networks and systems that guarantee a system that can be in continuous operation throughout the years.</p>
<p>Not only that, they were involved in wars against enemies proxying the major global world powers across Africa, India and Asia. They held their ground pretty well and where betrayed by several international players all with their filthy interests, spreading propaganda about the plight of the african (which, obviously, wasn't completely uncalled for for Africa in general) brothers while helping in the destruction of countries that were at the time some of the highest quality of life countries in Africa, all so they could set up their oil operations and fight the &quot;bad&quot; portuguese that were enslaving the poor africans. Then after the so called revolution, civil wars, some that still are ongoing. I know there's at times interests behind both, but this just comes to prove that there's no natural &quot;african unity&quot; so far, even in the same countries, sometimes comunities sharing the same native language for centuries, they still fall to tribalism and in-fighting. So it can't all be fault of the westerner, independently if they did also hedious acts.</p>
<p>It's interesting that the country of the &quot;Liberté, Fraternité et Egualité&quot;, as soon as Portugal found a profitable oil exploration in Angola started forming the first &quot;freedom fighter&quot; in Congo, that would later lead some of the first &quot;rebels&quot; against Portugal. They should add another one to their slogan, &quot;et suiné&quot;. Trés high-couture.</p>
<p>And you can see the continuation of this on the narratives and how they're told. When people say &quot;Portugal&quot; was exploring these countries and took these countries, they're basically re-writing history - and I'm not saying that the Portuguese didn't do no wrong, pretty sure that is not the case - by framing it has if the &quot;infrastructure&quot; that existed in these countries had been stolen, or occupied by the colonizer, when in truth, they had all been planned, paid and erected by the Portuguese since around the 1500s. But when you tell the history in a certain way the picture you create in the mind of others is different. For instance, if you're black growing up in a western country, going through an education and propaganda system that perpetuates this kind of ideas without ever showing the counterpart, it's probably hard to not grow hateful.</p>
<p>You also see this for instance in many online indian comments, when the topics go around the &quot;cast system&quot;, you'll see plenty of accounts making comments on how the cast system was introduced by the western elite, that before it was all peachy peachy. But history doesn't agree with this. I, by random chance, happened upon some information regarding a battle in India, between the Portuguese and an Indian General, where the Indians in an totally outlandish numeric advantage still managed to loose. As it seems, the general that lead the attack took that loss in such a way that he relinquished his duties and went to follow a monastic life. One interesting detail though, is that it seems that the portuguese had managed to get the help from some indian natives, that seemed to be &quot;dalits&quot;. Meaning &quot;untouchables&quot;. It's funny that the appearance of &quot;dalits&quot; in indian societies has probably to do with some dogmatic stance on meat eating, since that is considered unclean, and probably, because in many ways they agree on Ahimsa, non-violence, the only way to properly &quot;show&quot; them that their way of life wasn't welcomed was to turn them into dalits. Who knows right?</p>
<p>Another example is about the Inquisition, for instance in Goa. For all I could find, the Inquisition only acted on christians, it didn't have jurisdiction at all over non-christians. But, because the government was portuguese, and hence Catholic Christian, any person that was Catholic Christian would be in better light to improve its standing socially, economically, etc, as is natural, irrespective of what we might feel about it - there's probably certain positions that wouldn't be accessible unless you were a Catholic Christian. It's the same as when there's leftist governments and they fill positions with their allies. So this meant that many people would search for conversion, sometimes with only the objective of reaping the benefits of that status, but underneath would keep the same rituals, beliefs and ways of life.</p>
<p>I can believe that for instance in continental Portugal the inquisition was used, at least at times, to take things from people based on fake testimonies and so on. But in India it kinda doesn't make sense if you think about it. The portuguese had supremacy on the ocean, they won several battles completely outnumbered, made alliances with locals, passed laws to incentivise mixed marriages, etc. If they would want to take whatever they wanted (from lands they already controlled) they would have don't you think? Why would they do this half-assed dance to get to that? Bringing Inquisition to another continent, delegating part of the power to another institution, etc. But then I also don't know, it could be that in fact there were more abuses than cases like those, but it would seem that is not the case.</p>
<p>It's like when the marxistards attack Portugal, and the Spanish, and so on, and say things like, yeah they came and gave mirrors for lands, and blá blá blá. Again the same thing, these are the kind of things that pre-programmed retards spew. Things people who don't have a functioning brain say.</p>
<p>A mirror takes a civilization to be made. It's so unnatural that most animals take a long-while to understand, when they do, that its their own reflection. Of course, here you can say, they don't because they're not very bright, but you can, that nonetheless the Europeans knew the value of those things and as such were taking advantage. Ok. Now take a deep-breath and just think for a second, these same Europeans were buying fucking condiments with high quality grade weapons, mostly more advanced than what any of those local populations had access to.</p>
<p>Why would they trade condiments for weapons and ammunitions? The reason you shouldn't speak isn't because you're not entitled to a voice, it's because you're a fucking retard.</p>
<p>Another example. Many well-off women during slavery times would use slave milk-maids. This is always spun as an example of horrific treatment, by abusing a women for her milk to feed another woman's child. And while in part that can be viewed that way and I would agree that I don't want forced feeding, how do you concile a well-off women allowing their most cherished thing (at least most important even if not cherished, at that time offspring was an even bigger thing) to feed on the tits of a black woman and create an emotional attachment to another mother figure, that happens to be black. Don't you think there's something also a bit less ugly hiding in this act? Have you ever noticed how even across species, if you take care of a calf, a dog, a bird, a lion, or any other mammal, since they're newborns, that they will create an attachment to you for life. This would probably been known for centuries because animal husbandry has been a thing for quite a while.</p>
<p>So would you say that those children that would have been fed by black slave women would when growing up be less or more emotionally attunned to them, perhaps to their condition, and so on?</p>
<p>On the same topic, the miscigenation topic. Marxists will bring the fact that many paintings and cultural (propaganda at that time wasn't formalized but this would be similar) artifacts when dealing with the black african population in any positive light would always depict them as either being inserted on white households, being mixed race with whites, etc, not ever as example just by being black.</p>
<p>While this is in part true, and kinda can make sense to arguee that perhaps more only black lifting culture could have been produced, at the same time, you're again arguing that these evil people, that thought blacks were sub-human, closer to animals than to them, would somehow ignore all those ideas they had about them and go on and procreate, make families, and communities with them? It's that your thesis. That they were knowingly interbreeding with a lower species to produce handicapped offspring? Sounds really smart, I'll give you that. Not only that, but also, if the culture that arrived was &quot;white&quot;, and they want to integrate the others, how would they properly depict that idea of integration other than the mixing of two different people into a mixed offspring?</p>
<p>But what gets me the most is the fake-revolutionaires. You know the ones that when they're in their democratic (they call fascist, colonizors, opressors, etc) countries they make all these noises, insult people, many times using lies either knowingly or unknowningly, as some of the examples already talked here, and nothing happens to them because guess what, for all its faults it's the best we managed without Kings of any kind that allows anyone to speak their mind, even when it's directly connected to their anus. But they could take their sorry asses, work one year anywhere eating ramen to put up enough money and then open their cellphone, book a trip, get a uber, enter a plane, fly directly to any country that they so like where they were explored so badly by the colonizers, get another uber, go to the place to check-in, all done through the cellphone, and go do manifestations right there where people are still trafficked and sold for dollars on a daily basis.</p>
<p>But they don't do that. Why? Because they would be killed and thrown into some road sideway and no-one would find them ever again.
Yet they don't do that but go on public insulting, in all kinds of ways, people that lived 500 years ago, some who crossed oceans multiple times, spending months in the sea open to dying from the most varied causes, who setup schools in the middle of hellish places, who many times protected native populations from the greed of other colonizers AND OTHER NATIVES, in places where mosquitoes carry diseases capable of killing you while you sleep, sometimes doing the months long trip back to arguee in favour of the natives, sometimes getting killed, imprisoned or executed in these missions, yet these fuck tards that never did anything for anyone else than themselves (and in this I count family as themselves) think they have the right to come insult people that aren't here to defend themselves and with resources that amount to 0 in today's world changed completely the history of the planet while they repeat worn out slogans from their little propaganda books behind their keyboards.</p>
<p>Going back to the &quot;propaganda&quot;. So when we look at the 46% literacy levels left by the Estado Novo against the current state we kinda see that they actually, in 50 years, did the same percent wise and starting from a base that was setup up earlier by someone else, those they criticize. If you then start thinking that in this process the access to education became paid, the taxes grew and the services detiorated, it starts looking a bit like incompetence. Then think, not only that but they basically had what amounts to &quot;infinite&quot; money coming from the EU.</p>
<p>So the &quot;Estado Novo&quot;, not only was having 3 wars to fight (Portugal currently, as many other NATO members, weren't even keeping with the agreed 2% spenditure...) set up education systems, not only on continental Portugal but also to some extent in the Ultramar, increased the gold reserves in an absurd manner, a pillow that now these incompetent corrupt pigs are sitting in while keeping Portugal out of a world war and making bank while at it. If you start analysing these things you start to understand why the only thing that is talked about this time is the secret police, lack of liberties, persecutions, etc. They don't talk how they were betraying their country by fomenting the growth of USSR influence inside the country and ultramar territories. Because when you see the result of the communist doctrine (that to be truthful they couldn't entirely know at the time) today, and how the history went, you can't help but think that from the point of national security and truth, the secret police were right, as uncomfortable as that is to say and were in fact too lenient (not that if they had been less, they wouldn't have perhaps faced an uprising earlier, but ultimately, they were right but didn't manage to act on that with enough contudency).</p>
<p>So what do we have now? A society of doctors, where most people go to finish higher education at the University level but all put their covid masks, because the statistics for flu (there wasn't any possible covid test then...) in the flu season were so high, then you see the data, flu cases 0, covid X where X is roughly the same number of annual flu cases that suddenly dropped down to 0. Don't forget to not catch sun. So what is this reality I'm living in? Is it the short bus reality? A God joke? A random fart? What is it? The only way I would be so shameless while behaving in certain ways would be if I knew I was in a simulation, like some NPC where my own self being the equivalent of a metaphysical turd wouldn't matter, because it was what had to be done as an NPC. Maybe in Christian terms it would be the equivalent of saying a reality where the Devil is the lord and everything in it an illusion of his own making. It's weird isn't it.</p>
<p>It's funny how some weeks ago Maduro was cheering on Putin's Ukraine invasion and hoping for a &quot;swift&quot; takeover. Must suck to get ass fucked while you're taking a nap, but perhaps next time you don't wish for other people to loose their lives, freedom and right to self-determination to appease your pig friends. You're probably not feeling that smart now. Imagine being willing to drag your people into a war with someone capable to put you back into the neolithic in a single night of work, coming all fanfarre, waving his little sword around like some sort of brave heroic leader, so you can keep making your country poorer so you get richer.</p>
<p>Isn't it funny how the left always ends up tangled deeply with crime networks? It's almost a modus operandi. They disarm the population, relax the criminal penalties in name of tolerance, re-education, defund the police, invite foreigner agents to setup bizzybizzy, while always claiming for higher taxes, delivering shit.
Have you noticed that Brazil for instance has some homicide rates that are almost at the level of war zones? Then you see these politicians all involved in drugs, prostitution, crime. Like the mafias this usually starts with at least a fair purpose, to give power to their community. But soon once power becomes established they start working against their own communities - not always directly but increasingly skimming and skimming and skimming and directly when someone dares to question. They loose the Robin Hood initial aura, that came with the protecting of the Italians or Irish, or Latinos, or the dispossessed, whatever, from the discrimination and attacks of other communities and get them respected, the lives improved but then, due to the greed that never ends, slowly metamorphosing into pigs.</p>
<p>And the left has decided to ally with criminals for the most part, in fact it's very in line with their philosophies, that power will not be exchanged freely by those who hold it, so it has to be taken by force. Isn't it funny that then they go on and immediately pass laws to disarm the populace? Fishy hummm.</p>
<p>Now I wonder, so these people believe, many really believe in this, to this day, that killing others, including innocent people through terrorist attacks, because they didn't want to share/give what was theirs in name of their abstract &quot;soviet international&quot; fairytale, was fair and necessary. A question of almost justice. Ok. So what would you think would be justice for people that have stolen that which is not even theirs? And in many times in magnitudes higher amounts than some of these other cases. Execution of them and their families in the public square? Execution of them, and any directly related family that is an adult and sterelization of the children?</p>
<p>I mean, if you compare the supposed &quot;crime&quot;, I would say that that, in a scale that tries to be fair, would still not match what they did to so many people.
This is not to say that the great industrialists/landowners of the time were some peachy smelling flowers, obviously, but I always find it funny how these people are always searching to divide others and then go on behaving like a retarded parrot cheering for their club without any thought given to the contradictions. Because if I was born at that time and in poverty as many did, I would have probably became communist/extreme-left leaning, because even if I did know it was ultimately wrong, as said before, to correct a wrong route, you sometimes have to sail in the wrong direction for a while. But today? With all we know?</p>
<p>Have you ever seen communists or socialists that dodge paying taxes? Have you ever thought how our modern countries work in economical terms?</p>
<p>You see they keep expanding the public entourage across all board, tied up with their man made constitutions treated as if they were God given and immutable, which is funny for people that are always pointing their fingers to religion (except the Muslim pedophile religion) mocking them for believing a &quot;fairy tale&quot; document, but then they do similar, has if it was given by god, when you think about it, how does it make sense? Aren't you doing exactly the same, except for you it's this particular document that is treated as if God given, because it goes with your club?</p>
<p>Lets do an exercise. Lets say we're in Narnia, and Narnia's current available state budget is 10.000€ and Narnia's private economy is worth 10.000€ too. I live in Narnia too, I open a business selling my services to clients outside of Narnia, after paying for the priviledge and being treated like some sort of criminal by the Narnia retarded public officers. Everybody in Narnia is very smarty-pants. They created a system that you need to open a LTD responsability company, with a society by quotas but single ownership, yet you have to do all the rituals as if you had a quorum to respect, have to hire an accountant to basically submit the papers that they already have or can be submitted online, that can't give you informations about anything. Tells you to go do the registering of the company on a &quot;friends&quot; office, where they charged 280€, on top of the regular 200€ you have to pay the state, to submit an online form, don't even have prepared a small binder with some instructions, information, nothing, they leave the contacts names in the official systems with their own, no follow up, nothing. 280€ for half an hour and then go whining about digital nomads and how much they make... Oh, almost forgot, and when I visited, before returning with the papers and everything ready, they had told me 200€, but then it was after all 280€ - since that was tax they &quot;thought I knew&quot;. This is the kind of people that live in Narnia, always behaving as if their pig behaviours are fault of others and not themselves.</p>
<p>So I opened the business in Narnia, the state received 200€, plus 80€ of the taxes from the office, the % of the accountant, the office got 200€ too.</p>
<p>The state now has 10.280€, the economy grew to 10.200€, so on...
Now I pay my first salary. As I said I work as a freelancer, now through a company and I had chosen a 2.000€ salary. My rental alone, plus internet, water, electricity, gas, phone, etc, would easily reach 800€ and more during winter - in a house where another pig from Narnia faked an energetic certificate and then when putting all documents in the contract binder, oopsie, just slipped it under the bag thinking I wasn't seeing and forgot to include the forged A category energetic certificate, because well, if that house is even a D would be too much, from raining inside, non-isolated ceiling windows with 3 finger gaps on the attic, etc, but that's another story. From that salary, because this is a company, in my name, with myself as a worker, the company pays out of its pocket (mine) the base salary, plus alimentation stipend that is legally required, one 12th of both the vacation and christmas subsidies, paid by the company each month or in total at certain dates (in this case I divided it to monthly payments).</p>
<p>So basically we're recycling the money through the tax system so they can skim it as many times as possible. They skim a bit in every one of these payment &quot;steps&quot; - from a nominal contract of 2.000€ I, &quot;the worker&quot;, received 1.826€. But the company spent 3265€ (2450€ and an additional 815€ in Social Security) for the worker. Notice that I as an employer don't get any benefits from this, even though it's the employer who's bringing all this money from OUTSIDE the country and paying these things.</p>
<p>These numbers are all intentionally hidden, so that you don't understand how much the company actually pays for your work, so that they then can say &quot;oh, they only pay 850€&quot; or whatever when in truth is they pay much higher than that. Just take this example, the nominal contract value is 2000€ base salary, but in total the company spent 3200€ and the worker got 1800€. Adjust this to the reality of Narnia.</p>
<p>So after I paid from my own money, that was paid by someone outside Narnia, we can make the accounting again.</p>
<p>So now the state received close to 1.400€ in taxes, from this single payment monthly. So now the state has 11.680€, the economy has 12.000. This is so because in this case the money come from outside Narnia so both parts of the economy grow. Notice that the only benefits I get for this are as the &quot;worker&quot;, I as the &quot;entreprenour&quot; that brings this businness I don't get any social security, or anything.</p>
<p>If you now take a public servant, that makes 2000€, the same nominal contract, how do you think we get the money needed to cover the total costs of 3200€? Let's see.</p>
<p>The public servant gets paid 1826€ just like me. So if the state has <code>10.000 - 1.826 = 8.174€</code>. The private economy now has 11.826€ (the employee received the money, so now that money is part of the private pool). But the state employee also has to get his social security, subsidies, deslocation stipend, holidays, etc, all of that covered, after all, not only that, this person when retires will continue to be paid from the public treasury. So the state also had to cover the remaining 1.400€, so the state actually has 6.774€. And obviously the state entered a &quot;contract&quot; with this employee that guarantees after some years that they will have social security (unemployment, retirement, etc), that's why we're removing that value from the state pool, because those are extra outputs that need to be covered when the time comes (obviously, they'll be used to cover current expenses, due to how budgeting works, it's always behind, which is great because you can steal and only down the line does it break, when you're already writing books about the great public work and being paid to give talks).</p>
<p>So the difference when I pay, from having received money from outside, is that both economies, private and state, grow, while when government employees get paid, they get paid with the money from the state. So we could say that the objective of a state is to properly manage taxation first and foremost, since it's with that that then it can create a sustainable army, infrastructure, education systems. But when you look at the ways, the processes these states have built you can see they're completely incompetent, right? They don't even manage to properly tax their people because they create these pig kafka systems where they can continuously steal and hide.</p>
<p>But it's not only that, if I now buy anything I pay IVA for it, and that IVA goes directly to the state, the business gets my money, which again, didn't even exist in the economy before, because this money comes from OUTSIDE. When this person that gets paid from the public treasury goes to pay, obviously also pays IVA, but when you look, that money came in the first place from where it's going back to. So there's only changing of hands. Obviously, most public workers will be in families with people doing other work and so incomes will mix and come from different places, yet, it's pretty easy to understand what I'm saying here - if you can't understand it you really shouldn't be in any position of governance.</p>
<p>So if I'm bringing in 5.000€ per month from the outside, if 10% of the active population of Narnia did that, it would mean Narnia (not the state alone, but assuming the people would need to spend money to live there, and store it in local banks, which is the truth) would be receiving per year (50.000 people X 5.000€ X 12 months) 3.000.000.000€, from outside the country alone directly into their economy, both state and to Narnia banks that hold that money, while exporting basically services. But the retards can't do maths so this is what you get.</p>
<p>Now take into account that many of the people in these positions act like they're the last cookie on the packet, because you have to go through them to get anything done. All of this while being paid their whole fucking life with the money of others. Obviously, I don't want to work for free, neither do I want others to do that, but if your income is solely tied to the contributions of others you better know your place you little retard.</p>
<p>How do you solve this? With transparency built into the systems, automated processes, some sort of limitation on contracts for public placements. I mean, why would someone be expected to work all their life in a guaranteed position, other than when involved with secret/security services/clearances? This removes accountability, the desire to change, because letting things stay as they are is the surest way to guarantee continued employment, not rocking the boat, even if you're seeing unlawful or plain criminal actions - and in a way you can understand why it is so, if you have children to feed, house to pay - so the system has to be built to not suffer from it where it shouldn't.</p>
<p>I should be able to do ANY action online, and then, for a whole class of actions, I would need to go to any public service and do a quick input of the action number, on a biometric machine, that would then just print a receipt of confirmation. So you could have all the basic actions be automatic just online and anything more important guarded behind a simple two-step process that doesn't require any other input from any other person.</p>
<p>So you do the action online in the morning, then during your lunch break you go to validate it if needed. And now you have video-proof of the individual (because the public service has video surveillance) going to a public service, then entering the &quot;confirmation&quot; code along with their biometric details to confirm, and getting a physical printed receipt, the state has the digital records and also the physical original/duplicate emitted to the person.</p>
<p>This means it's not only or all &quot;digital&quot; and as such no longer problematic from a security and data integrity, tampering, hacking, etc, point of view, because important actions will need you to physically go to a place, solve a biometric challenge and confirm your intent, while producing along the way a bunch of auditable artifacts without needing ANYONE ELSE to waste time dealing with it.</p>
<p>The same with transparency. Taxes, payments, subsidies, should be calculated automatically from the minute you're interested in opening a company/getting a job and you fill a form putting employees salaries, expected revenue, etc. And this would be VALID legally unless you did something illegal or you didn't include the proper items to simulate. Otherwise, if what you input is the truthfull information you should know up to the cent each month, each payment, each tax return, you will get with exact dates.</p>
<p>This should all be automated, because it's exactly in all these manual processes and shit systems that the corruption hides. All under a cover of pretending to be small minded and a little retarded to not raise suspicions. There's other things that are in dire need of happening. Public servants in any condition with exception of special forces/secret services have to have a completely transparent financial life. All public institutions have to provide publicly and guarantee its ACCESSIBILITY all their spenditures and who signed them. All benefits, bonuses, social security payments need a confirmation period of at least 8 years for any public (state) company, public servant, politician, etc. So that there's time to both access the repercussions of the work/spenditure and if any illegality surfaces.</p>
<p>This removes all the shit-layer of parasites and sanitises the pigsty. But the pigs are already squeaking and putting their fingers where they shouldn't.</p>
<p>Once they come with vacination passports and integrated bio-medic chips, you'll need to force, even if by way of civil war, that it all starts by implanting those in the public servants, politicians and friends and make sure the system is publicly disclosed and auditable. You don't need to play this game. They have no power but they want to convince you they have. You don't need any of these things. If they made law be respected, criminals swiftly dealt with, proper immigration laws, you wouldn't have all these problems they want to solve with these solutions.</p>
<p>It's like forcing age-restriction on internet access, the way they projected is just for control. My first porn movie was a friend who found it in someone's secret stash. I would have been at most 11 or 12 I guess... It was a VHS tape, called &quot;Dog luck&quot; (or something translated to that in english), it was a German movie, where two girls take turns getting fucked by a german shepard dog under the caring eye of a male adult who just talks through the actions. I didn't need internet for this. And this wasn't the first and only VHS we had access to, a girl once found one and we did a cinema session in her house, about 12 people, to watch it, this time only humans were in the movie. Except one guy and one girl at that time, we the boys were really cuckolds, and didn't take any action... All this to say, that what this creates is a black market, the same way we got older people to buy us cigarettes, alcohol, you'll have kids trying to get sexual content access - intermediated by adults, is this better? I think the effort should be in making OS/hardware that are safer by default (not locked down, just not purposefully written to be full of holes), but even if that doesn't happen, parents already have ways of preventing access.</p>
<p>The same with some of the internet related rulings, the little pigs in the European Parliament pass these laws where they fine the big players but then everything just stays the same, no real change, just extorsion. Then they want respect. Imagine this, you want to build some business say like Paypal, Uber, AirB&amp;B, in Europe... How do you think that would go in terms of regulamentation? Would never get off the ground, because all those other interests would not allow it - taxi associates have to pay for certification, etc, same with rentals, etc. These platforms all skip that substituting it with their own selection processes. So what happens? European businesses can't go these ways and try these models but then Europe goes and says, you know what, they, they can operate under these models, it's just you  that can't. Then they have the grant mafia, where there's all this innovation grants and it's always the same guys getting them, a burocratic paradise where many leech off, because you need a whole bunch of burocratic tokens that require some know-how and inner knowledge to make it go through. Are all projects crap? Obviously not right, but damn, it would be much proper to diminish this and remove costs for creating enterprises, from micro to whatever.</p>
<p>Look at the European Union, all these years and not a single unified way of making business across countries and for the external world for small/self-owned companies. Everything the same as if you were doing business locally, same taxes even though you're acting as an exporter for services, etc. It was more important to be throwing moustache parties.</p>
<p>Then instead of removing taxes and impediments to creating businesses they just make it worse, individually and at the European level. And my problem with this is not that I don't think something like an European Union doesn't make sense, but what they set up is basically this system to skim money without any accountability, delegating decisions behind doors to unelected interests. The grant systems, loans, funds, little mafia run groups taking turns grabbing funds. Instead of this crap, wouldn't it be easier to just remove all costs to create, manage and close a company?</p>
<p>That would be something huh? But then where would you do your &quot;socially worried redistribution of wealth&quot; to your friends pockets?</p>
<p>You would have 2 free company registration, maintenance, wtv per 5 years. If any or both of those companies produced 1 year of employment for at least yourself with taxes paid, you would get again free company registration, maintenance, etc. Just plain, straightforward systems. Then if you want to audit, guess what, easy. The person building something, even if its own income and covering his supposed &quot;social costs&quot; to the state, shouldn't be paying this shit.</p>
<p>So people that go around jumping from job 6 months, another 6 months, then unemployment benefits, then another job, then unemployment, they get these benefits, and those that are at least covering their asses are extorted. At least remove the costs idiots.</p>
<p>Now lets talk about on-line identities. I projected a platform a long-time ago, dvouch, that would allow digital validation of identities without leaking anything at all, if the user so wished. The way it worked is the user registers on dvouch, then chooses from a preset of vetted platforms, and dvouch would connect on behalf of the user to those other platforms and extract information from them. Things like upwork.com, facebook.com, youtube.com, image selling platforms, etc. The idea was to expand it to all relevant platforms in use as dvouch grew. Anything where you had an identity and public information (or accessible behind the granted access). What this would allow is that for instance, I could use any alias for my name publicly, for my dvouch profile, then connect to my real upwork profile, by showing proof of credentials usually, extract the job history from upwork, and now display it in several manners. If I want anonymity I would choose to show that data as simple bucketed graphs - number of jobs on dates, success rate, total feedback, without showing any particular details that could identify me or those who hired me.</p>
<p>If on the other hand I wanted my profile to be public and publicize those same jobs I have completed, I could instead show not only the aggregate graphs but also a list of all jobs, with their rates, feedback, etc.</p>
<p>Because only a single account can be connected to each of these external providers and because it's dvouch that handles the data and displays it, the user can customise a lot of its profile but not the data points, those are always based on data coming from the real apis dvouch interacts with, anyone seeing that profile can know that whoever that is, those jobs happened, the stats are at least real. Then the profile had a simple contact form section where you could interact with the user by sending a message. No e-mail was disclosed, but allowed you to verify that by getting an answer it was really who the person said he was, as in, if someone sent you the profile and said, this is me, check my work history, you could go there and then send a direct message to the owner of that profile and establish if it's the same person that's talking with you.</p>
<p>Of course, without any way of really verifying the person who created the profile and connected the other platforms (no state/global identity system), it could be someone else, but since only one same account from each of the other platforms can be connected to a single dvouch account, there's not many ways to take advantage of it, and is not much different than someone hiring someone to do the take-aways interview, phone-call or whatever and faking some documents, it will always happen, but in this case it will at most happen to 1 of each external profiles per account.</p>
<p>I do believe that states will have at some point to create such systems (publicly) and that in part, as it already happens, surveillance will be built-in. Still, a citizen should be able to yes, claim they are someone online and prove it, through some secure government provided platform (auditable), because this is useful, but at the same time should be able to go anonymously online, and up to a certain extent not be tracked by 3rd parties and by the state unless in a grave suspicion (in the case of the state it's not even that the records can't be there, they theoretically could, but they shouldn't be accessible in any way unless under strict but reasonable conditions, and that's the hard part). It should also be possible to opt simply out of this system by not being forced to participate through it, but I imagine that even due to simple commodity and the advantage of having more data, that it will be impossible to not be registered somehow, as is already the case today, except it will be accessible almost real-time digitally instead of having to be dug for in real-life book keeping (while still being kept in that form as well somehow).</p>
<p>This also automatically separates things for those using the on-line spaces. If you're saying something outrageous but you're using a non-verified account to post it, I can approach it with a bit more caution from the get go, be the idea, the content, etc. If you use your verified name, your real person, exposing yourself, then even if I don't agree with you, I can know it's you. I can perhaps understand better some things. The problem with this is that it would sink the current web-ad model. Nonetheless, I don't see any reason why ads can't be made to work in other ways as well.</p>
<p>Then you have minorities and the discourse of the left again, all corrupt many times in bed with these criminal organisations. For instance in Portugal there as always been a problem with gypsies. Ever since I remember, when growing up an older boy, Luís (I can't recall if he was 14 or 15 or something like that, he was not like friend directly because he was older, but he lived closed by one of my best friends and was friend with that friend's older brother, who was his age), got stabbed to death by a gypsy, on a local fair, like animal/agricultural fair. Gypsies that traveled nomadically would visit fairs and sell their wares and this time although I don't recall exactly what happened I'm pretty sure it was not warranted a death, because most probably he was telling them something he was right about. Nothing happened. No one could find the gypsies nor who did it. A kid just lost is life like that.</p>
<p>But there was never, not even from those who knew the kid, any direct antagonism towards &quot;gypsies&quot; simply because they came from gypsy families. There were at least 2 gypsy families that had settled in that city, one had a big store, big window panes, right at the entrance in one of the nicer avenues of the city, the other a bar of dubious nightly activities (and there was at least a more famous &quot;night&quot; bar in town owned by others). The textile/clothing owners no-one mentioned them as gypsies, unless to disambiguate, they were no longer gypsies although they still had a bit of style, flavour if so to say, maybe 1st or 2nd generation to have settled, super nice people from all the times I interacted with them. The other family one of his sons was a very good friend of mine and of our other mutual friends, even though the bar was shady, our parents had no problem in letting us sleep over in his house and he did sleep over mine and others in our normal group as anyone else. No one even thought of calling them gypsies, much less gypsies in any negative way and one or two generations before they would have been living the way that the term gypsy usually implies.</p>
<p>Later on in another city, more to the interior, I was working on a coffe/restaurant and there was also seasons in the year where gypsies would come to visit. In that place the owner wouldn't allow us workers to serve gypsies before paying after too many fights involving unwillingness to pay, threats and so on, he decided no more that year. I asked why and I was told that besides those issues he himself had in the place, there were always robberies while they were camped around the city. Every year. I never thought about it anymore, later also went to university so only returned in the weekends of my first university year to wait weddings and, in one of those weekends, I was told that a gypsy encampment near that city was set on fire. They never settled again there and all those issues seemed to suddenly disappear. There's also other nearby cities that have some issues with them but there they live in government provided habitation, they're not part of these nomadic groups.</p>
<p>So there's always been quite a bit of tension. At some point I lived in Peniche, where there's also a notorious community living nearby. I knew a few people living there, some doing uber and bolt, many people complained, refused to serve the area where they lived for deliveries or pickups, due to multiple issues, or fear of issues. One day I had to go to the hospital, I went very early. I arrived not sure if around 8 or 9 am, there was big gypsy family sitting on the waiting room. A mother with many children below age 6 and one or two older than that. Immediately after sitting one of the boys come talk, ok, I strike conversation, it's a kid right, 4 or 5 years old, 3 phrases in he's doing gun signs and &quot;pum pum&quot; sounds and telling me his father has guns. Cool. I cut him off. Remember, owning guns in Portugal is illegal unless you have a license, some rifles can be owned if you have an hunting license. I sincerely doubt any has a license obviously...
After some 15 minutes I start hearing the sound of water running. One of the little girls, sitting by the side of her mother, both on those waiting plastic chairs, was on her knees on top of it pissing on the chair, dripping to the floor. And the mother nothing. Just like it was not her problem.</p>
<p>5 minutes after the father comes out, sitting on an hospital wheelchair, surrounded by a doctor, a nurse, with serum being drip-fed, all good. The mother picks their children and just goes away and leaves the chair in a puddle of piss dripping to the floor, not a single word.</p>
<p>I don't know but, honestly, my parents always owned dogs and cats throughout me growing up, and I don't ever recall a dog or a cat not learning to not piss or shit inside houses, not even only our house, just houses in general in less than a month. Somehow these people, can't teach 4 or 5 years old these things. So they're in an hospital paid by portuguese people (they're the ones who don't want to be portuguese), raised by the Portuguese Republic, offering them a service they don't even pay, nor their community can provide themselves, as they don't pay other things (these types of gypsies, not gypsies by blood that have decided to just be portuguese and made their lifes, these &quot;true&quot; gypsies many live in government provided habitations where they pay a symbolic rent, sometimes 5€, and get benefits for every child, which they then can marry as young as they please between them because of culture and keep doing this).</p>
<p>There was at least 1 mother with a little child there, a bit far away from me, I was in the middle with a bunch of chairs between, looking like she just woke up at 6 am to bring the child, had to miss work, also known as &quot;looking like shit&quot;, and some other people there too. And then they're sitting on a public hospital, with the known conditions and already known problems, and they still have to put up with more this shit, and if they say something they'll have problems, might be threatned or assaulted (my daddy has gun bum bum) and police, public officers do nothing. So the people that do everything as required in their duties as citizens are the ones that have to put up with this sort of crap caused by others who refuse to be part of that society in any helpful way. The same for the guys threatning people in public transport, taking over public spaces like they're theirs, what the fuck are we doing over there?</p>
<p>So instead of animals learning how to behave, it's the others that have to live like animals to not offend them. And the left is playing a problematic game, because this is the continent of Hitler and many others, and then when it has no longer a proper non-violent solution you'll look away and pretend it's not your fault in the way you've lead and modeled society. Obviously, this is also because in part you have allies in these criminal communities.</p>
<p>And this is the problem and mark of moral bankrupcy of the left. Without even talking about Islam and other things. They prefer to protect the poor guy who just happened to have robbed, did armed threats to others, sometimes exerted violence and even killed others, for the sake of their psychological being, at the expense of the physical, financial and psychological health of all others.</p>
<p>The same for immigration, oh, you want to become nationality X? Well, how nice of you. We're ready to welcome you, you just need 15 years of a clean sheet, no criminal charges plus either with 70% of that time under declared working contracts with private companies or generating a tax return of &gt; than X. Complete fluency in the language. Etc. If you really want to move to another country you won't be doing shit, sorry. Yes, everyone (most) is entitled to a second chance but sometimes you screw too badly too. When I go on vacation I make an effort to not disrespect those that are hosting me, even if I diametrically think the opposite of them, although nowadays that doesn't happen because I just refuse to go where I don't agree with the general culture, but when I was younger I didn't have neither the same knowledge nor the same views but yet I still thought it was essential to not disrespect the countries I'm visiting even though I would also be paying tourist taxes, I didn't treat it as an entitlement, because honestly my individual contribution is in itself insignificant. To then see people that come and behave that way? What the fuck are we on over there?</p>
<p>So to me is a big surprise when people move to these countries with the pretext of asylum or looking for better life, or working, studying and then they get involved in drug dealing, crime, robberies, gangs, organised violence, human trafficking and/or are unable to let go of their &quot;cultural&quot; habits. If you want to keep them and they conflict with those who are already there, then go back to where you came from.</p>
<p>And it's not that those things don't happen with natives, but it's different when someone comes to another country and behaves that way, it tells you all you have to know about the mentality of that individual/group and you're not bound at all to please, host, or protect them, other than protect those that are law abiding and really intent on becoming citizings, as you would any future citizen. It's important to not let racist discourse take over because while it can be tempting there's cases where people of those cultures, race (?), language, as I spoke before, that were and are completely integrated so it's an awful thing, not even awful, it would be outrageous, to allow those to suffer because of those others.</p>
<p>And this is the last point. The actions of these so-called communities and their own ignoring of these problems hurts their own community but they don't care, they just want to keep behaving as animals and throwing blame on someone else.</p>
<p>I'll give you an example with something else entirely. Once, a couple years ago, I was watching a youtube video roundtable with some westerners and some vietnamese, and one of the vietnamese guys in the middle of talking about how vietnamese people are regarding foreigners just goes, yeah except black people, not really a racist thing, it's just we don't want that kind of behaviour here. This was around the time two afro-american (not american-africans, or amerindafricans) girls had made a scene in a nail/hairdresser shop in Bali that made the rounds in youtube and got them in serious trouble, they walked into a shop, got all the services, then refused to pay and then started threatening the shop girls and if I remember correctly started a physical altercation.</p>
<p>So now a black guy that never did shit to no one is just thought of as sort of an animal because of the behaviour of some.</p>
<p>And this is not like white foreign people aren't getting into issues in these countries regularly too, but usually it's in night out shops, bars, with alcohol, nightlife, it's a different thing than out of nowhere on a sunday morning a violent confrontation after applying nail gel or dread locks, that's why on those venues there's security, extra policing etc, because even locals will get into night life related altercations regularly.</p>
<p>Ultimately, you have to ask yourself, if someone robs, attacks, threatens, sometimes kills, others, out of nothing else but self benefit, or some petty shit, how does this person &quot;want&quot; to be part of society? Why should this person even have access to that option after behaving in such ways?</p>
<p>This is how you end like Europe, a corrupt bureocratic pigsty, infinite money for football stadiums, whore parties, dinners and lunches for the friends and the gang, doing the great business and a never ending expansion of the pig machine.... Age of retirement going up, houses out of range for most people, prices through the roof on everything, sale of profitable state enterprises (by these socialists, communists, leftist pigs), industries with years upon years of advantage getting taken for lunch by countries which got the technology from Europe and USA, no army, unable to spend 2% for self-defense... 2%... Again for football, pigsty non-profits, retards, cunts and dick suckers, shitty enterprises, for the friends, for COVID vaccinnes, for the professional commentators on TVs, journals, etc, there's always money for that. A woman from PSD was on the Parlament for 10 years got retired with a lifetime of 5.000€ monthly payments ... From the time she retired, taking into account life expectancy, she will get from the state in those remaining years more than 3 million €, paid by you, by doing nothing, after having been paid all those other years...</p>
<p>Isn't it interesting what these pigs did with Europe? Imagine a continent with this much potential, can't even fuck to replacement rates, more than half the population addicted (between alcohol, recreational and medical drugs) and the only ones interested in settling here are whores, pigs, criminals (from petty to high-crime) and people who come from places where they live worse than pets in the West... This is what Europe has become, the second biggest consumer market in the world can't even renew themselves... You know why? Just pigs and retards like you would like to live in the world you created, and this is what you see... It's people who have invested too much and can't get out (life, house, work, etc) the politicians and civil servants that have for life positions, those who can't get out and the drugged out retards that just go through life like some fucking automaton that can't even string a logical thought from A to C even though he spent 12 years on public education, 9-to-5. Really amazing.</p>
<p>Hope this expanded your view of the world and make you more aware of the reality in which you thread.</p> ]]></description>
    </item>
    <item>
       <title>Creating an Ecto Enum Type</title>
       <link>https://micaelnussbaumer.com/posts/creating-an-ecto-enum-type</link>
       <pubDate>Thu, 06 Jan 2022 16:30:00 +07</pubDate>
       <guid>https://micaelnussbaumer.com/posts/creating-an-ecto-enum-type</guid>
       <description><![CDATA[ <p><a href="/posts/criar-um-ecto-type-como-enum">in portuguese</a></p>
<p>Today I'm going to write about a little Ecto type I use regularly in most Elixir projects I work in. Basically, it's an enum wrapper that allows you to use a limited set of <code>:atoms</code> or <code>&quot;strings&quot;</code> values in your <code>Ecto</code> schemas definitions.</p>
<p>You might be wondering why a writing an enum type when <code>Ecto</code> ships with an <code>Ecto.Enum</code> type since <code>v3.5</code>. The main reason is the typing of the &quot;type&quot; itself and sharing this type between multiple schemas.</p>
<p><code>Ecto.Enum</code> is great and very handy for most regular cases where you simply want to be able to deal with <code>atom</code> versions of strings in your schemas and Elixir logic, while being able to store them as strings automatically at the database level and be able to cast from <code>strings</code> to <code>atoms</code> - which is a pretty normal usecase when dealing with external parameters or inputs.</p>
<p>To show you what I mean lets say you have a schema like:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">User.Action</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">  <span style="color: #9d79d6;">use</span> <span style="color: #7ad5d6;">Ecto.Schema</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4">  <span style="color: #86abdc;">schema</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;users_actions&quot;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="5">    <span style="color: #86abdc;">belongs_to</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:user</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7">    <span style="color: #86abdc;">field</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:action</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:string</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="8">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="9"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Now, this is a totally valid schema. But if you have a limited set of values that <code>:action</code> might assume, right now you have no way of ensuring that when dealing with casting / inserting records of this type of schema the strings that are passed on are valid.</p>
<p>You might create this constraint at the database level, and if it's an essential part of your business logic you probably should keep alongside such constraint (although it makes it more onerous to update and change), but even if you don't, it would be nice to at least in your business logic be able to treat this <code>:action</code> field as having only a value from a set of known, well defined, values without having to explicitly read the field/param and manually checking it.</p>
<p>This is where <code>Ecto.Enum</code> can be used. Applying it to our schema means:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">User.Action</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">  <span style="color: #9d79d6;">use</span> <span style="color: #7ad5d6;">Ecto.Schema</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4">  <span style="color: #86abdc;">schema</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;users_actions&quot;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="5">    <span style="color: #86abdc;">belongs_to</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:user</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7">    <span style="color: #86abdc;">field</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:action</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Ecto.Enum</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">values: </span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:bid</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:request</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:upload</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:pay</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="8">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="9"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>In this case, we basically defined as valid values only that specific set of atoms and so when casting against that schema field, any string value, or atom, that matches those atoms if converted would also be a valid value.</p>
<p>What this gives us is:</p>
<ul>
<li class="sub-li">the ability to cast params and make sure the <span class="since">action</span> field is only valid if it conforms to those values, ex:</li>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #dfdfe0;">params</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #81b29a;">&quot;user_id&quot;</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #f4a261;">1</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;action&quot;</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #81b29a;">&quot;bid&quot;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3"><span style="color: #7ad5d6;">Ecto.Changeset</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User.Action</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">params</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:user_id</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:action</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div></code></pre>
<li class="sub-li">The ability to deal strictly with the <span class="since">atom</span> versions in our programs logic, by being sure that after casting or retrieving a record from the database it will have to conform, ex:</li>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">log_action?</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User.Action</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">action: </span><span style="color: #dfdfe0;">action</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="2">    <span style="color: #86abdc;">do: </span><span style="color: #dfdfe0;">action</span> <span style="color: #aeafb0;">in</span> <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:bid</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:pay</span><span style="color: #aeafb0;">]</span>
</div></code></pre>
<p>And in many cases this is enough. But if we, for instance, want to use that same <code>&quot;action type&quot;</code> in another schema, then we have to duplicate its definition - and it's never really the same <code>&quot;type&quot;</code>, we need to keep both (or more versions if used in more places) in synch. It also doesn't expose directly the normal <code>cast/load/dump</code> functions that can also be useful, in some contexts. For instance, you might want to cast a single string somewhere and depending on the success of such take a path on your code or another.</p>
<p>It also doesn't allow you to use <code>integer</code> versions for the underlying enum definition at the database level, nor do some useful tricks with casting &amp; evaluating the value when dealing with &quot;translations&quot; - e.g. some external datasource uses some strings values that you don't want to store as they are, nor assume as valid for the field, but instead convert them to your app's version, or you simply assert their &quot;equivalence&quot;, even if they have different representations - say one external source uses <code>bidding</code> but all others including yours use <code>bid</code>. You don't want to allow <code>bidding</code> to be stored or deal with it internally, but you want to be able to cast <code>bidding</code> as <code>bid</code>.</p>
<p>There's also the fact that it doesn't expose a <code>@typespec</code> that you can use, which can be useful as well, when using dialyzer (which you, most of the times, should be) or simply when writing <code>@spec</code>s in your code's documentation (which you should always strive to do).</p>
<p>None of these are showstoppers though and if you don't need any of the additional functionality then just using <code>Ecto.Enum</code> is a significant improvement over bare strings and might cover all your requirements while being part of <code>Ecto</code> itself (meaning, no additional dependencies or code to maintain).</p>
<p>If we were to be writing a <em>single</em> <code>Ecto.Type</code>, following the examples before,  we could do something such as:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">User.Action.Type</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">behaviour </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4">  <span style="color: #9d79d6;">def</span> <span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:string</span>
</div><div class="line" data-line="5">
</div><div class="line" data-line="6">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_types </span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:bid</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:request</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:upload</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:pay</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="7">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_strings </span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_types</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">Atom</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_string</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">]</span> <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="8">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_map </span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_types</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Atom</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_string</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="9">
</div><div class="line" data-line="10">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_inverse_map </span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_types</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Atom</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_string</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="11">
</div><div class="line" data-line="12">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">type </span><span style="color: #86abdc;">t</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">::</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reverse</span><span style="color: #aeafb0;">(</span><span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_types</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:|</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&amp;</span><span style="color: #aeafb0;">1</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #aeafb0;">2</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="13">
</div><div class="line" data-line="14">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">load</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="15">
</div><div class="line" data-line="16">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_types</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="17">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_strings</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_map</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="18">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:error</span>
</div><div class="line" data-line="19">
</div><div class="line" data-line="20">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_types</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_inverse_map</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="21">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_strings</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="22">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:error</span>
</div><div class="line" data-line="23">
</div><div class="line" data-line="24">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">embed_as</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:dump</span>
</div><div class="line" data-line="25">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">equal?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #f4a261;">true</span>
</div><div class="line" data-line="26">
</div><div class="line" data-line="27">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">equal?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data_1</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data_2</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="28">    <span style="color: #9d79d6;">case</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data_1</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data_2</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="29">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&lbrace;</span> <span style="color: #81b29a;">&#39;&lbrace;&lbrace;&#39;</span> <span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">same</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">same</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #f4a261;">true</span>
</div><div class="line" data-line="30">      <span style="color: #738091;">_</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #f4a261;">false</span>
</div><div class="line" data-line="31">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="32">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="33"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Breaking it down:</p>
<ul>
  <li class="sub-li">declare a behaviour of <span class="since">Ecto.Type</span> for our module (this ensures we'll get warnings if we don't implement some functions that are expected to be defined for such behaviour)</li>
  <li class="sub-li">Declare a function <span class="since">type/0</span> that returns the underlying type of the <span class="since">Ecto.Type</span> (what is used to persist values of this type in the database), in this case <span class="since">:string</span> (which ecto uses to abstract over all char, varchar, and text column types)</li>
  <li class="sub-li">Declare a <span class="since">typespec</span>, that returns the valid atoms this type represents</li>
  <li class="sub-li">From the list of possible atoms, we create a list of their counterparts in string form, and two module attributes to store the mappings between <span class="since">atom<->string</span> versions and vice-versa</li>
  <li class="sub-li">Declare all required behaviour functions for the <span class="since">Ecto.Type</span>, since we have lists of both <span class="since">atoms</span> and <span class="since">strings</span> representing values we consider valid, we can use these in guards, to cast them appropriately to their atom form when in string, and the same for dumping them from atoms to strings</li>
</ul>
<p>As you can see it's easy to create an <code>Ecto.Type</code> that provides us with a more constrained set of values and helps us being more assertive on our code about what we expect.</p>
<p>It also makes it so that now we can actually cast those values independently of a schema. We can just do <code>User.Action.Type.cast(&quot;bid&quot;)</code> to validate if it's a valid action according to the type.</p>
<p>If you don't mind the copy pasting and changing the <code>@valid_types</code> list whenever you want to add a new type it's fine to use it like this. You can just use this as a blueprint then change the module name, and the list of values whenever you need to define another enum.</p>
<p>This already has some advantages, besides being able to cast the values independently of schemas, the type itself is now independent of their declaration in a schema, and as such can be used in multiple schemas as well.</p>
<p>We could also easily make it use integers for its underlying representation, as in a conventional enum. But we can also write a macro that effectively does all of this for us with a single line of code. Our objective is to have a macro that enables us to write the previous <code>User.Action.Type</code> module as:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">User.Action.Type</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">  <span style="color: #9d79d6;">use</span> <span style="color: #7ad5d6;">TypedEnum</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">values: </span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:bid</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:request</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:upload</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:pay</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="3"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Followed by using it on the schema:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">User.Action</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">  <span style="color: #9d79d6;">use</span> <span style="color: #7ad5d6;">Ecto.Schema</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4">  <span style="color: #86abdc;">schema</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;users_actions&quot;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="5">    <span style="color: #86abdc;">belongs_to</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:user</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7">    <span style="color: #86abdc;">field</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:action</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">User.Action.Type</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="8">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="9"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>And if we want to deal with atoms in our inner logic, but store them as integers in the database, while still allowing the casting of stringed versions:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">User.Action.Type</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">  <span style="color: #9d79d6;">use</span> <span style="color: #7ad5d6;">TypedEnum</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">values: </span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">bid: </span><span style="color: #f4a261;">0</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">request: </span><span style="color: #f4a261;">1</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">upload: </span><span style="color: #f4a261;">2</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">pay: </span><span style="color: #f4a261;">3</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="3"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Let's breakdown what our module will need to do:</p>
<ul>
<li class="sub-li">Implement the <span class="since">__using__</span> macro, so that it can be "used" in the way we wrote in the previous examples</li>
<li class="sub-li">Be able to distinguish between a plain list of <span class="since">atoms</span> or a <span class="since">Keyword</span> list being passed as <span class="since">values</span> to allow both integer and string based enums at the database layer</li>
<li class="sub-li">Allow the caller to write any additional cases for the <span class="since">cast</span>\<span class="since">dump</span> logic of the <span class="since">Ecto.Type</span> behaviour</li>
<li class="sub-li">Implement automatically a <span class="since">typespec</span> for it, reflecting all the valid atoms it can assume</li>
<li class="sub-li">Raise on <span class="since">invalid values</span> being passed to provide compilation time blowups.</li>
</ul>
<p>This is our final module and we'll break it down after:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1">
</div><div class="line" data-line="2"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">TypedEnum</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="3">  <span style="color: #9d79d6;">defmacro</span> <span style="color: #86abdc;">__before_compile__</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_env</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="4">    <span style="color: #738091;"># these are inserted in the before_compile hook to give opportunity to the</span>
</div><div class="line" data-line="5">    <span style="color: #738091;"># implementing module to define additional variations</span>
</div><div class="line" data-line="6">    <span style="color: #9d79d6;">quote</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="7">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:error</span>
</div><div class="line" data-line="8">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:error</span>
</div><div class="line" data-line="9">      <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #dfdfe0;">data</span>
</div><div class="line" data-line="10">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="11">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="12">
</div><div class="line" data-line="13">  <span style="color: #9d79d6;">defmacro</span> <span style="color: #86abdc;">__using__</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">opts</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="14">    <span style="color: #dfdfe0;">values</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Keyword</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">fetch!</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">opts</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:values</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="15">    <span style="color: #dfdfe0;">mod</span> <span style="color: #aeafb0;">=</span> <span style="color: #f6b079;">__CALLER__</span><span style="color: #aeafb0;">.</span><span style="color: #dfdfe0;">module</span>
</div><div class="line" data-line="16">
</div><div class="line" data-line="17">    <span style="color: #dfdfe0;">is_int_enum?</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Keyword</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">keyword?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="18">
</div><div class="line" data-line="19">    <span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">is_int_enum?</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="20">      <span style="color: #f4a261;">true</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="21">        <span style="color: #86abdc;">:ok</span> <span style="color: #aeafb0;">=</span> <span style="color: #86abdc;">validate_int_enum</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="22">        <span style="color: #86abdc;">bind_as_integer_version</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="23">
</div><div class="line" data-line="24">      <span style="color: #f4a261;">false</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="25">        <span style="color: #86abdc;">:ok</span> <span style="color: #aeafb0;">=</span> <span style="color: #86abdc;">validate_string_enum</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="26">        <span style="color: #86abdc;">bind_as_stringed_version</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="27">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="28">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="29">
</div><div class="line" data-line="30">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">validate_int_enum</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="31">    <span style="color: #9d79d6;">with</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">true</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">&lt;-</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:length</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">length</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">&gt;</span> <span style="color: #f4a261;">0</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="32">         <span style="color: #aeafb0;">&lbrace;</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">true</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">&lt;-</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:format</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">all?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #86abdc;">valid_int_enum?</span><span style="color: #aeafb0;">/</span><span style="color: #aeafb0;">1</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="33">      <span style="color: #86abdc;">:ok</span>
</div><div class="line" data-line="34">    <span style="color: #9d79d6;">else</span>
</div><div class="line" data-line="35">        <span style="color: #dfdfe0;">error</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #86abdc;">raise_error</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">error</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="36">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="37">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="38">
</div><div class="line" data-line="39">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">validate_string_enum</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="40">    <span style="color: #9d79d6;">with</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">true</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">&lt;-</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:length</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">length</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">&gt;</span> <span style="color: #f4a261;">0</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="41">         <span style="color: #aeafb0;">&lbrace;</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">true</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">&lt;-</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:format</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">all?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">/</span><span style="color: #aeafb0;">1</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="42">      <span style="color: #86abdc;">:ok</span>
</div><div class="line" data-line="43">    <span style="color: #9d79d6;">else</span>
</div><div class="line" data-line="44">        <span style="color: #dfdfe0;">error</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #86abdc;">raise_error</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">error</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="45">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="46">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="47">
</div><div class="line" data-line="48">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">valid_int_enum?</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">k</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">v</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="49">    <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">k</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #86abdc;">is_integer</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">v</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="50">
</div><div class="line" data-line="51">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">raise_error</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:length</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="52">    <span style="color: #86abdc;">do: </span><span style="color: #9d79d6;">raise</span> <span style="color: #81b29a;">&quot;TypedEnum expects `:values` to be a list or keyword list with at least 1 element&quot;</span>
</div><div class="line" data-line="53">
</div><div class="line" data-line="54">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">raise_error</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:format</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="55">    <span style="color: #86abdc;">do: </span><span style="color: #9d79d6;">raise</span> <span style="color: #81b29a;">&quot;TypedEnum expects the format of `:values` to be a keywordlist with the atom version as the key and an integer as the value (e.g.: [atom_key: 1, another_possible: 2, ...]), or a list of atoms for the string enum version (e.g.: [:atom_key, :another_possible, ...])&quot;</span>
</div><div class="line" data-line="56">
</div><div class="line" data-line="57">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">bind_as_integer_version</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="58">    <span style="color: #9d79d6;">quote</span> <span style="color: #86abdc;">bind_quoted: </span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">atoms_ints: </span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">mod: </span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">]</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="59">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">before_compile </span><span style="color: #7ad5d6;">TypedEnum</span>
</div><div class="line" data-line="60">
</div><div class="line" data-line="61">      <span style="color: #dfdfe0;">atom_integer_map</span> <span style="color: #aeafb0;">=</span>
</div><div class="line" data-line="62">        <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="63">          <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="64">        <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="65">
</div><div class="line" data-line="66">      <span style="color: #dfdfe0;">string_integer_map</span> <span style="color: #aeafb0;">=</span>
</div><div class="line" data-line="67">        <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atom_integer_map</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="68">          <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Atom</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_string</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="69">        <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="70">
</div><div class="line" data-line="71">      <span style="color: #dfdfe0;">string_atom_map</span> <span style="color: #aeafb0;">=</span>
</div><div class="line" data-line="72">        <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="73">          <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Atom</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_string</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="74">        <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="75">
</div><div class="line" data-line="76">      <span style="color: #dfdfe0;">integer_atom_map</span> <span style="color: #aeafb0;">=</span>
</div><div class="line" data-line="77">        <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="78">          <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="79">        <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="80">
</div><div class="line" data-line="81">      <span style="color: #dfdfe0;">strings</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">map</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #7ad5d6;">Atom</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_string</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="82">      <span style="color: #dfdfe0;">atoms</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">map</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #dfdfe0;">atom_val</span> <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="83">      <span style="color: #dfdfe0;">ints</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">map</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #dfdfe0;">int</span> <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="84">
</div><div class="line" data-line="85">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">behaviour </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="86">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="87">      <span style="color: #9d79d6;">def</span> <span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:integer</span>
</div><div class="line" data-line="88">
</div><div class="line" data-line="89">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:valid_atoms</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="90">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:valid_strings</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="91">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:valid_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">ints</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="92">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:validation_mappings</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">string_atom_map</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="93">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:validation_mappings_atoms</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">atom_integer_map</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="94">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:validation_mappings_strings</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">string_integer_map</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="95">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:validation_mappings_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">integer_atom_map</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="96">
</div><div class="line" data-line="97">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">type </span><span style="color: #86abdc;">t</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">::</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reverse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:|</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&amp;</span><span style="color: #aeafb0;">1</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #aeafb0;">2</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="98">
</div><div class="line" data-line="99">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">spec </span><span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:atoms</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">:strings</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">:ints</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">::</span> <span style="color: #86abdc;">list</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">t</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">list</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">String</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">t</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">list</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">integer</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="100">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">&quot;Given a desired format returns the matching values for that format&quot;</span>
</div><div class="line" data-line="101">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">type</span> <span style="color: #aeafb0;">\\</span> <span style="color: #86abdc;">:atoms</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="102">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:ints</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ints</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="103">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="104">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:strings</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="105">
</div><div class="line" data-line="106">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="107">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">load</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="108">
</div><div class="line" data-line="109">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="110">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="111">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="112">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="113">
</div><div class="line" data-line="114">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="115">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="116">
</div><div class="line" data-line="117">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_integer</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ints</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="118">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings_ints</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="119">
</div><div class="line" data-line="120">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="121">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="122">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="123">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings_atoms</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="124">
</div><div class="line" data-line="125">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="126">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings_strings</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="127">
</div><div class="line" data-line="128">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_integer</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ints</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="129">
</div><div class="line" data-line="130">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">&quot;Dumps but raises in case of non-valid data&quot;</span>
</div><div class="line" data-line="131">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump!</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="132">        <span style="color: #9d79d6;">case</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="133">          <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">value</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="134">            <span style="color: #dfdfe0;">value</span>
</div><div class="line" data-line="135">
</div><div class="line" data-line="136">          <span style="color: #738091;">_</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="137">            <span style="color: #9d79d6;">raise</span> <span style="color: #7ad5d6;">Ecto.CastError</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="138">              <span style="color: #86abdc;">message: </span><span style="color: #81b29a;">&quot;Unable to dump:: </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;"> ::into:: </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span><span style="color: #aeafb0;">(</span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="139">              <span style="color: #86abdc;">type: </span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="140">              <span style="color: #86abdc;">value: </span><span style="color: #dfdfe0;">data</span>
</div><div class="line" data-line="141">        <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="142">      <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="143">
</div><div class="line" data-line="144">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="145">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="146">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">embed_as</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:dump</span>
</div><div class="line" data-line="147">
</div><div class="line" data-line="148">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="149">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="150">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">equal?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">term_1</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">term_1</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #f4a261;">true</span>
</div><div class="line" data-line="151">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">equal?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">term_1</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">term_2</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">term_1</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">==</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">term_2</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="152">
</div><div class="line" data-line="153">      <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="154">        <span style="color: #86abdc;">do: </span><span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings_atoms</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="155">
</div><div class="line" data-line="156">      <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="157">        <span style="color: #86abdc;">do: </span><span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings_strings</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="158">
</div><div class="line" data-line="159">      <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_integer</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ints</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="160">        <span style="color: #86abdc;">do: </span><span style="color: #dfdfe0;">data</span>
</div><div class="line" data-line="161">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="162">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="163">
</div><div class="line" data-line="164">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">bind_as_stringed_version</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="165">    <span style="color: #9d79d6;">quote</span> <span style="color: #86abdc;">bind_quoted: </span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">atoms: </span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">mod: </span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">]</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="166">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">before_compile </span><span style="color: #7ad5d6;">TypedEnum</span>
</div><div class="line" data-line="167">
</div><div class="line" data-line="168">      <span style="color: #dfdfe0;">strings</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">map</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #dfdfe0;">entry</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #7ad5d6;">Atom</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_string</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">entry</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="169">      <span style="color: #dfdfe0;">mapped</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">zip</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">|&gt;</span> <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">into</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="170">
</div><div class="line" data-line="171">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">behaviour </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="172">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="173">      <span style="color: #9d79d6;">def</span> <span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:string</span>
</div><div class="line" data-line="174">
</div><div class="line" data-line="175">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:valid_atoms</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="176">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:valid_strings</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="177">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:validation_mappings</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">mapped</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="178">
</div><div class="line" data-line="179">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">type </span><span style="color: #86abdc;">t</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">::</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reverse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:|</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&amp;</span><span style="color: #aeafb0;">1</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #aeafb0;">2</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="180">
</div><div class="line" data-line="181">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">spec </span><span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:atoms</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">:strings</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">::</span> <span style="color: #86abdc;">list</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">t</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">list</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">String</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">t</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="182">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">type</span> <span style="color: #aeafb0;">\\</span> <span style="color: #86abdc;">:atoms</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="183">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="184">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:strings</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="185">
</div><div class="line" data-line="186">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="187">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">load</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="188">
</div><div class="line" data-line="189">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="190">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="191">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="192">
</div><div class="line" data-line="193">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="194">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">String</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="195">
</div><div class="line" data-line="196">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="197">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="198">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="199">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Atom</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_string</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="200">
</div><div class="line" data-line="201">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="202">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="203">
</div><div class="line" data-line="204">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">&quot;Dumps but raises in case of non-valid data&quot;</span>
</div><div class="line" data-line="205">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump!</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="206">        <span style="color: #9d79d6;">case</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="207">          <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">value</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="208">            <span style="color: #dfdfe0;">value</span>
</div><div class="line" data-line="209">
</div><div class="line" data-line="210">          <span style="color: #738091;">_</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="211">            <span style="color: #9d79d6;">raise</span> <span style="color: #7ad5d6;">Ecto.CastError</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="212">              <span style="color: #86abdc;">message: </span><span style="color: #81b29a;">&quot;Unable to dump:: </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;"> ::into:: </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span><span style="color: #aeafb0;">(</span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="213">              <span style="color: #86abdc;">type: </span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="214">              <span style="color: #86abdc;">value: </span><span style="color: #dfdfe0;">data</span>
</div><div class="line" data-line="215">        <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="216">      <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="217">
</div><div class="line" data-line="218">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="219">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="220">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">embed_as</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:dump</span>
</div><div class="line" data-line="221">
</div><div class="line" data-line="222">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="223">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="224">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">equal?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">term_1</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">term_1</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #f4a261;">true</span>
</div><div class="line" data-line="225">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">equal?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">term_1</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">term_2</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">term_1</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">==</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">term_2</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="226">
</div><div class="line" data-line="227">      <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="228">        <span style="color: #86abdc;">do: </span><span style="color: #dfdfe0;">data</span>
</div><div class="line" data-line="229">
</div><div class="line" data-line="230">      <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="231">        <span style="color: #86abdc;">do: </span><span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="232">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="233">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="234"><span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="235">
</div></code></pre>
<p>We declare the <code>__before_compile__</code> macro that allows us to place some code in the module after everything else is in place, in this case we want to include some catch-all clauses. The reason we do it in the <code>__before_compile__</code> hook is that this then enables a user of the module to implement their own versions of those functions, which can be useful for instance to include clauses that cast correctly values that come from third party systems that we can't change, but we do not want to allow on our db, instead translate them to our versions.</p>
<p>Because the <code>load/1</code> function will already catch all possible terms and simply call <code>cast/1</code> we do not include it there.</p>
<p>Then the actual <code>__using__</code> macro.</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1">  <span style="color: #9d79d6;">defmacro</span> <span style="color: #86abdc;">__using__</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">opts</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">    <span style="color: #dfdfe0;">values</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Keyword</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">fetch!</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">opts</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:values</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="3">    <span style="color: #dfdfe0;">mod</span> <span style="color: #aeafb0;">=</span> <span style="color: #f6b079;">__CALLER__</span><span style="color: #aeafb0;">.</span><span style="color: #dfdfe0;">module</span>
</div><div class="line" data-line="4">
</div><div class="line" data-line="5">    <span style="color: #dfdfe0;">is_int_enum?</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Keyword</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">keyword?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7">    <span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">is_int_enum?</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="8">      <span style="color: #f4a261;">true</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="9">        <span style="color: #86abdc;">:ok</span> <span style="color: #aeafb0;">=</span> <span style="color: #86abdc;">validate_int_enum</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="10">        <span style="color: #86abdc;">bind_as_integer_version</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="11">
</div><div class="line" data-line="12">      <span style="color: #f4a261;">false</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="13">        <span style="color: #86abdc;">:ok</span> <span style="color: #aeafb0;">=</span> <span style="color: #86abdc;">validate_string_enum</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="14">        <span style="color: #86abdc;">bind_as_stringed_version</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="15">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="16">  <span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>This is a macro, so it will be called at compile time. We <code>fetch!</code> the <code>:values</code> key from the options - since it's required we use the <code>!</code> version in order to raise when it's missing. We then decide if the underlying enum will be integer or string based through a very simple heuristic. Are the <code>values</code> a keyword list or a plain list? If it's  keyword list then it must be an integer based enum, otherwise a string based enum.</p>
<p>Depending on that we do a check on the form of the values to make sure they comply and then generate the actual code to fill the caller module. Remember that this is a macro, so these checks/raises will occur at compile time allowing us to signal to the user of our module any problem.</p>
<p>We'll only go through the integer version since it's the most complex, but you should be able to then understand easily the stringed version too. The validation helpers are plain functions, but since they're called in the context of a macro they will raise at compile time. Lastly, both <code>bind_as_</code> functions do <code>quote</code> their contents so that these are placed in the calling module as code.</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">bind_as_integer_version</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">    <span style="color: #9d79d6;">quote</span> <span style="color: #86abdc;">bind_quoted: </span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">atoms_ints: </span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">mod: </span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">]</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="3">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">before_compile </span><span style="color: #7ad5d6;">TypedEnum</span>
</div><div class="line" data-line="4">
</div><div class="line" data-line="5">      <span style="color: #dfdfe0;">atom_integer_map</span> <span style="color: #aeafb0;">=</span>
</div><div class="line" data-line="6">        <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="7">          <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="8">        <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="9">
</div><div class="line" data-line="10">      <span style="color: #dfdfe0;">string_integer_map</span> <span style="color: #aeafb0;">=</span>
</div><div class="line" data-line="11">        <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atom_integer_map</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="12">          <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Atom</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_string</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="13">        <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="14">
</div><div class="line" data-line="15">      <span style="color: #dfdfe0;">string_atom_map</span> <span style="color: #aeafb0;">=</span>
</div><div class="line" data-line="16">        <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="17">          <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Atom</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_string</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="18">        <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="19">
</div><div class="line" data-line="20">      <span style="color: #dfdfe0;">integer_atom_map</span> <span style="color: #aeafb0;">=</span>
</div><div class="line" data-line="21">        <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="22">          <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="23">        <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="24">
</div><div class="line" data-line="25">      <span style="color: #dfdfe0;">strings</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">map</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #7ad5d6;">Atom</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_string</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="26">      <span style="color: #dfdfe0;">atoms</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">map</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #dfdfe0;">atom_val</span> <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="27">      <span style="color: #dfdfe0;">ints</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">map</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #dfdfe0;">int</span> <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="28">
</div><div class="line" data-line="29">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">behaviour </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="30">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="31">      <span style="color: #9d79d6;">def</span> <span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:integer</span>
</div><div class="line" data-line="32">
</div><div class="line" data-line="33">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:valid_atoms</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="34">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:valid_strings</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="35">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:valid_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">ints</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="36">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:validation_mappings</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">string_atom_map</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="37">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:validation_mappings_atoms</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">atom_integer_map</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="38">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:validation_mappings_strings</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">string_integer_map</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="39">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:validation_mappings_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">integer_atom_map</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="40">
</div><div class="line" data-line="41">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">type </span><span style="color: #86abdc;">t</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">::</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reverse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:|</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&amp;</span><span style="color: #aeafb0;">1</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #aeafb0;">2</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="42">
</div><div class="line" data-line="43">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">spec </span><span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:atoms</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">:strings</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">:ints</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">::</span> <span style="color: #86abdc;">list</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">t</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">list</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">String</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">t</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">list</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">integer</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="44">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">&quot;Given a desired format returns the matching values for that format&quot;</span>
</div><div class="line" data-line="45">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">type</span> <span style="color: #aeafb0;">\\</span> <span style="color: #86abdc;">:atoms</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="46">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:ints</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ints</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="47">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="48">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:strings</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="49">
</div><div class="line" data-line="50">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="51">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">load</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="52">
</div><div class="line" data-line="53">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="54">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="55">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="56">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="57">
</div><div class="line" data-line="58">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="59">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="60">
</div><div class="line" data-line="61">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_integer</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ints</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="62">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings_ints</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="63">
</div><div class="line" data-line="64">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="65">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="66">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="67">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings_atoms</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="68">
</div><div class="line" data-line="69">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="70">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings_strings</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="71">
</div><div class="line" data-line="72">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_integer</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ints</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="73">
</div><div class="line" data-line="74">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">&quot;Dumps but raises in case of non-valid data&quot;</span>
</div><div class="line" data-line="75">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump!</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="76">        <span style="color: #9d79d6;">case</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="77">          <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">value</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="78">.            <span style="color: #dfdfe0;">value</span>
</div><div class="line" data-line="79">
</div><div class="line" data-line="80">          <span style="color: #738091;">_</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="81">            <span style="color: #9d79d6;">raise</span> <span style="color: #7ad5d6;">Ecto.CastError</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="82">              <span style="color: #86abdc;">message: </span><span style="color: #81b29a;">&quot;Unable to dump:: </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;"> ::into:: </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span><span style="color: #aeafb0;">(</span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="83">              <span style="color: #86abdc;">type: </span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="84">              <span style="color: #86abdc;">value: </span><span style="color: #dfdfe0;">data</span>
</div><div class="line" data-line="85">        <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="86">      <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="87">
</div><div class="line" data-line="88">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="89">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="90">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">embed_as</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:dump</span>
</div><div class="line" data-line="91">
</div><div class="line" data-line="92">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="93">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="94">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">equal?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">term_1</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">term_1</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #f4a261;">true</span>
</div><div class="line" data-line="95">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">equal?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">term_1</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">term_2</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">term_1</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">==</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">term_2</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="96">
</div><div class="line" data-line="97">      <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="98">        <span style="color: #86abdc;">do: </span><span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings_atoms</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="99">
</div><div class="line" data-line="100">      <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="101">        <span style="color: #86abdc;">do: </span><span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings_strings</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="102">
</div><div class="line" data-line="103">      <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_integer</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ints</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="104">        <span style="color: #86abdc;">do: </span><span style="color: #dfdfe0;">data</span>
</div><div class="line" data-line="105">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="106">  <span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>We do <code>bind_quoted</code> passing the <code>values</code> as the variable <code>atoms_ints</code> and caller module as <code>mod</code>.</p>
<p>The generated code will include the <code>@before_compile</code> hook referencing this module where we defined it, <code>TypedEnum</code>. Then we use the keyword list of <code>atoms_ints</code> to generate a few different maps and lists that we'll use further down.</p>
<p>Because keyword lists of literal terms are literal proplists inside macros it makes them very ergonomic to use inside macros. They also provide a nice easy syntax to pass options as in this case.</p>
<p>So from the <code>values</code> keyword list (e.g.: <code>[val_1: 1, val_2: 2]</code>) we generate 4 maps:</p>
<ul>
  <li class="sub-li">A simple map version of the proplist, the prop key as map key and the integer as the value, e.g.: <span class="since">%{val_1: 1, ...}</span></li>
  <li class="sub-li">Another in the same form but now the keys as strings, e.g: <span class="since">%{"val_1" => 1, ...}</span></li>
  <li class="sub-li">Another string to atoms mapping, e.g: <span class="since">%{"val_1" => :val_1, ...}</span></li>
  <li class="sub-li">And lastly a integer to atom mapping, e.g: <span class="since">%{1 => :val_1, ...}</span></li>
</ul>
<p>These 4 maps will be used to fetch the right form of the enum depending on if we're loading or dumping it, and if the original data being passed in is in atom, string or integer form.</p>
<p>Then we generate 3 lists to aid us in adding guard clauses to our functions:</p>
<ul>
  <li class="sub-li">for strings, e.g: <span class="since">["val_1", ...]</span></li>
  <li class="sub-li">for atoms, e.g: <span class="since">[:val_1, ...]</span></li>
  <li class="sub-li">for ints, e.g: <span class="since">[1, ...]</span></li>
</ul>
<p>We put all these things as module attributes (so the caller module can access them if they want, with the <code>@...</code> syntax) and we use them to provide the helper function <code>values(type)</code>, that allows the user to retrieve the valid enum representations in any of its valid forms.</p>
<p>The <code>cast</code> functions of the <code>Ecto.Type</code> (and in our case the <code>load</code>) are used to transform values from their representation in the database, or from external requests, into our internal representation, which are atoms. Following this then means that if we trie to load or cast an atom that is a valid representation we just return that same atom since it's already in its correct form. If on the other hand it's a string (comes from an external request perhaps), or an integer (loaded from the database layer), we, with the aid of the mappings we assembled before, convert those into their atom version.</p>
<p>For the <code>dump</code> it's the same logic, but in this case the final form we want is the integer form, so we convert atoms and strings into their integer version, and if it's already an integer and a valid one we use that.</p>
<p>Otherwise, because of the guards we set up on each function, if the value they're called with is invalid, the catch all clauses that we set on the <code>@before_hook</code> will kick in and error at the ecto layer.</p>
<p>This allows still a user of the module to implement intermediate versions. Say one client that interacts with this is using a legacy version of the enums, where instead of <code>&quot;val_1&quot;</code> they were using <code>&quot;some_prop&quot;</code> as its identifier. We could set a specific clause on our caller module  handling that specific case, for example:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">ExampleCallerModule</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">  <span style="color: #9d79d6;">use</span> <span style="color: #7ad5d6;">TypedEnum</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">values: </span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">val_1: </span><span style="color: #f4a261;">1</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">val_2: </span><span style="color: #f4a261;">2</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;some_prop&quot;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:val_1</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="5">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;some_prop&quot;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">1</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="6">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;some_prop&quot;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:val_1</span>
</div><div class="line" data-line="7"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>And this would allow us to cast it, and even test its equality automatically by defining as well the <code>get_term</code> version for it.</p>
<p>I also like to add a specific <code>dump!</code> version that just calls <code>dump</code> underneath and raises in case <code>dump</code> returns anything else than an <code>:ok tuple</code>. The <code>get_term</code> are just helpers to simplify the equality checks.</p>
<p>And this folks, is all there is to it. The <code>stringed</code> version is very very similar, but simpler because it only has to deal with atoms and strings.</p>
<p>I opted to keep them as two separate functions because although there's some overlap and duplication going on, I think that having a whole bunch of conditionals on the macro for generating functions depending on if it's the integer or stringed version, and different module attributes, etc would just make it less straightforward to read and change if the need arises.</p>
<p>Now that you've seen how it works, if you don't want to write it yourself you can just include the package I've you can find it here in <a href="https://hexdocs.pm/typed_enum/TypedEnum.html">hexdocs</a> (or through github in <a href="https://github.com/mnussbaumer/typed_enum">mnussbaumer/typed_enum</a> and use it straightaway. Otherwise hope you could take away something useful.</p> ]]></description>
    </item>
    <item>
       <title>Criar um Ecto.Type como Enum</title>
       <link>https://micaelnussbaumer.com/posts/criar-um-ecto-type-como-enum</link>
       <pubDate>Thu, 06 Jan 2022 16:30:00 +07</pubDate>
       <guid>https://micaelnussbaumer.com/posts/criar-um-ecto-type-como-enum</guid>
       <description><![CDATA[ <p><a href="/posts/creating-an-ecto-enum-type">em inglês</a></p>
<p>Hoje vou mostrar um enumerador implementado como um <code>Ecto.Type</code>, que uso em quase todos os projectos de Elixir em que contribuo. É um tipo semelhante ao <code>Ecto.Enum</code> que permite utilizar <code>átomos</code> na lógica interna da aplicação, validar/transformar valores equivalentes na sua forma de caracteres, e ao mesmo tempo limitar os possíveis valores que determinado campo/coluna pode assumir. Como não há tradução actual para o tipo de &quot;string&quot;, no sentido em que é utilizado em programação, irei utilizar o termo <code>listagrama</code>, no sentido que uma &quot;string&quot; é uma lista de caracteres, e <code>gramma</code> em latim é símbolo/letra/desenho (hexagrama, etc), ou seja, uma lista de &quot;grammas&quot;.</p>
<p>Apesar do <code>Ecto</code> incluir um <code>Ecto.Enum</code> desde a versão 3.5, este sofre de alguns problemas:</p>
<ul>
<li class="sub-li">é declarado em conjunto com o esquema no qual é utilizado, o que não permite que seja partilhado facilmente entre esquemas,</li>
<li class="sub-li">não gera informações de tipo para usar em especificações,</li>
<li class="sub-li">não permite lógica adicional no tratamento de parâmetros adicionais,</li>
<li class="sub-li">não permite utilizar números inteiros para a representação do mesmo ao nível da base de dados (apenas grupos de caracteres)</li>
<p>Mesmo assim é por si só melhor do que usar simplesmente <code>string</code> como tipo de coluna nos casos em que sabemos que a mesma apenas pode assumir uma lista limitada de valores.
Para ilustrar isto, vejamos o seguinte módulo:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">User.Action</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">  <span style="color: #9d79d6;">use</span> <span style="color: #7ad5d6;">Ecto.Schema</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4">  <span style="color: #86abdc;">schema</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;users_actions&quot;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="5">    <span style="color: #86abdc;">belongs_to</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:user</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7">    <span style="color: #86abdc;">field</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:action</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:string</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="8">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="9"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Isto é um esquema totalmente válido, mas tanto quanto sabemos ao lê-lo é que o campo <code>:action</code> é um grupo de caracteres arbitrário. Neste caso, <code>:action</code> apenas pode assumir um número limitado de valores mas o esquema em si não nos transmite essa informação de forma alguma.</p>
<p>Claro que poderíamos criar restrições ao nível da base de dados, e em certos casos independemente de tudo o resto devemos certamente fazê-lo, mas isso continuaria a não providenciar informação alguma a nível do código da nossa aplicação sobre as possíveis restrições, nem ajudaria a transformar ou traduzir valores entre sistemas externos e a nossa representação interna para esses mesmos valores. Para obter isso necessitamos de emergir ao nível dos nossos esquemas quais são os valores possíveis para tais colunas.</p>
<p>Nesse caso, o <code>Ecto.Enum</code> ajuda-nos a fazer exactamente isso, por exemplo, utilizando o mesmo esquema anterior, mas agora atribuíndo um <code>Ecto.Enum</code> como tipo ao invés da simples <code>:string</code></p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">User.Action</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">  <span style="color: #9d79d6;">use</span> <span style="color: #7ad5d6;">Ecto.Schema</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4">  <span style="color: #86abdc;">schema</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;users_actions&quot;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="5">    <span style="color: #86abdc;">belongs_to</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:user</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7">    <span style="color: #86abdc;">field</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:action</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Ecto.Enum</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">values: </span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:bid</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:request</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:upload</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:pay</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="8">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="9"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Agora é visível que valores este campo pode assumir. Simplesmente por ler a definição do esquema sabemos que são <code>:bid</code>, <code>:request</code>, <code>:upload</code> e <code>:pay</code>.</p>
<p>Este tipo também nos permite então traduzir valores no formato de simples caracteres para o nosso formato interno de átomos, o que é bastante útil uma vez que se tivermos de tratar de validar submissões de dados externas ao nosso sistema, essas submissões serão certamente no formato de caracteres e não em tipos nativos a Elixir/Erlang, como é o caso de átomos. No entanto, após traduzidos, podemos ter a certeza que são não só válidos (há uma equivalência explicíta entre ambas as representações) mas que podemos escrever a nossa lógica interna com recurso apenas a <code>átomos</code>, o que para além de ser mais eficaz é também mais robusto.</p>
<p>Resumindo:</p>
<ul>
<li class="sub-li">dá-nos a habilidade de transformar e validar parâmetros:</li>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #dfdfe0;">params</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #81b29a;">&quot;user_id&quot;</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #f4a261;">1</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;action&quot;</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #81b29a;">&quot;bid&quot;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3"><span style="color: #7ad5d6;">Ecto.Changeset</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User.Action</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">params</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:user_id</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:action</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div></code></pre>
<li class="sub-li">permite-nos, como mencionado anteriormente, usar estritamente a versão de <span class="since">átomo</span> na nossa lógica interna, pois sabemos que após ser validado terá de conformar-se a essa representação:</li>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">log_action?</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User.Action</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">action: </span><span style="color: #dfdfe0;">action</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="2">    <span style="color: #86abdc;">do: </span><span style="color: #dfdfe0;">action</span> <span style="color: #aeafb0;">in</span> <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:bid</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:pay</span><span style="color: #aeafb0;">]</span>
</div></code></pre>
</ul>
<p>Como <code>átomos</code> em Elixir e Erlang são internamente representados como números inteiros, é bastante mais performante utilizá-los, tanto para serializar ou de-serializar. Grupos de caracteres necessitam de muito mais trabalho para serem comparados e avaliados.</p>
<p>O que o <code>Ecto.Enum</code> adiciona é por si só em grande parte dos casos suficiente. É sempre melhor do que usar definições de tipos que permitem grupos arbitrários quando sabemos que apenas determinados valores são válidos.</p>
<p>Mas se por exemplo, agora quisessemos utilizar este mesmo tipo que definimos no <code>User.Action</code> noutro esquema, teríamos de duplicar esta definição, e não haveria ligação efectiva entre ambos, a não ser que fossemos buscar os valores a algum módulo/função partilhada e, mesmo nesse caso, a ligação não é formal, o tipo não é o mesmo nem é possível representá-lo como tal.</p>
<p>Para além disso, não temos também acesso a funções de validação independentes do esquema. O tipo sendo declarado no esquema em si, é parte do mesmo e as suas validações ocorrem no contexto de um esquema de <code>Ecto</code>. Adicionar claúsulas específicas para tratar de casos especiais é também impossível ou bastante mais complicado do que necessita de ser.</p>
<p>Adicionalmente, caso queiramos guardar tais valores como números inteiros ao nível da base de dados, também não o podemos fazer uma vez que o <code>Ecto.Enum</code> assume apenas listagramas (<code>strings</code>) como a coluna ao qual está associado.</p>
<p>Por último, não gera um <code>typespec</code> para o tipo. Caso usemos <code>dialyzer</code> na nossa aplicação não temos forma de transpor as restrições definidas no esquema para especificações de tipos para documentação (e consistência de documentação das interfaces).</p>
<p>No entanto é, como referido, bastante melhor que utilizar apenas <code>:string</code> como tipo, e por vezes também não necessitamos de mais nenhuma funcionalidade.</p>
<p>Caso necessitemos, vejamos primeiro como poderíamos definir um <code>Ecto.Type</code> independente para este caso em particular :</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">User.Action.Type</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">behaviour </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4">  <span style="color: #9d79d6;">def</span> <span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:string</span>
</div><div class="line" data-line="5">
</div><div class="line" data-line="6">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_atoms </span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:bid</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:request</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:upload</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:pay</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="7">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_strings </span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_atoms</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">Atom</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_string</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">]</span> <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="8">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_map </span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_atoms</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Atom</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_string</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="9">
</div><div class="line" data-line="10">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_inverse_map </span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_atoms</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Atom</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_string</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="11">
</div><div class="line" data-line="12">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">type </span><span style="color: #86abdc;">t</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">::</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reverse</span><span style="color: #aeafb0;">(</span><span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:|</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&amp;</span><span style="color: #aeafb0;">1</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #aeafb0;">2</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="13">
</div><div class="line" data-line="14">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">load</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="15">
</div><div class="line" data-line="16">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_atoms</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="17">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_strings</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_map</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="18">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:error</span>
</div><div class="line" data-line="19">
</div><div class="line" data-line="20">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_atoms</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_inverse_map</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="21">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">valid_strings</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="22">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:error</span>
</div><div class="line" data-line="23">
</div><div class="line" data-line="24">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">embed_as</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:dump</span>
</div><div class="line" data-line="25">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">equal?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #f4a261;">true</span>
</div><div class="line" data-line="26">
</div><div class="line" data-line="27">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">equal?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data_1</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data_2</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="28">    <span style="color: #9d79d6;">case</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data_1</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data_2</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="29">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&lbrace;</span> <span style="color: #81b29a;">&#39;&lbrace;&lbrace;&#39;</span> <span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">same</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">same</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #f4a261;">true</span>
</div><div class="line" data-line="30">      <span style="color: #738091;">_</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #f4a261;">false</span>
</div><div class="line" data-line="31">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="32">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="33"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Analisando o módulo:</p>
<ul>
<li class="sub-li">declaramos que o módulo implementa o comportamento (<span class="since">@behaviour</span>) de um <span class="since">Ecto.Type</span> (o que nos garante avisos e erros aquando da compilação no caso de nos esquecer-mos de implementar alguma função)</li>
<li class="sub-li">declaramos uma função <span class="since">type/0</span> que resolve no tipo interno que o módulo representa (o que será utilizado aquando da serialização para a base de dados). Neste caso resolve em <span class="since">:string</span> (ou seja, a coluna na base de dados será uma coluna de texto - varchar, char, text, etc)</li>
<li class="sub-li">declaramos um <span class="since">typespec</span>, que resolve numa lista contendo todos os átomos válidos para este tipo</li>
<li class="sub-li">utilizando essa lista de átomos válidos (<span class="since">@valid_atoms</span>) geramos uma lista de listagramas que correspondem directamente às respectivas versões dos átomos, assim como dois atributos do módulo para guardar o mapeamento entre os mesmos, átomos->listagramas e listagramas->átomos</li>
<li class="sub-li">declaramos todas as funções requeridas pelo comportamento <span class="since">Ecto.Type</span> - uma vez que temos uma lista compostas por todos os átomos e outra por todos os listagramas válidos, podemos utilizar essas listas como cláusulas de restrição nas funções requeridas e dessa forma facilmente definir como se devem comportar.</li>
</ul>
<p>Como podemos ver, é simples criar um <code>Ecto.Type</code> que represente um grupo restrito de valores, ajudando-nos a tornar o nosso código mais assertivo e explícito (e por conseguinte mais compreensível também).</p>
<p>Permite-nos também transformar e validar termos independentemente de um qualquer esquema. Podemos por exemplo executar <code>User.Action.Type.cast(&quot;bid&quot;)</code> para validar o termo <code>&quot;bid&quot;</code>, que neste caso seria válido visto ser a representação em listagrama do átomo <code>:bid</code>.</p>
<p>Caso copiar ou replicar este módulo com as devidas alterações sempre que necessitemos de um tipo novo para um outro grupo de valores não for um problema, podemos utilizar esta versão e fazer exactamente isso, utilizando isto como a &quot;planta&quot; para todos os outros.</p>
<p>Esta versão já demonstra algumas vantagens relativamente ao <code>Ecto.Enum</code>, nomeadamente a capacidade de fazer transformações &amp; validações de termos independentemente de esquemas, assim como ser utilizado em vários esquemas, sem requerer duplicação de código ou código adicional para os manter actualizados - futuras alterações aos valores do tipo ocorrem apenas no módulo que o define.</p>
<p>Uma vez que controlamos também o funcionamento interno do mesmo poderíamos facilmente modificá-lo para que serializasse os valores como números inteiros. No entanto, o melhor seria criar uma macro que faça tudo isso por nós, permitindo-nos aceder essa funcionalidade com uma simples linha de código. Tendo isso em mente, o nosso objectivo é criar uma macro que nos permite escrever o módulo <code>User.Action.Type</code> anteriormente exposto, como:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">User.Action.Type</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">  <span style="color: #9d79d6;">use</span> <span style="color: #7ad5d6;">TypedEnum</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">values: </span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:bid</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:request</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:upload</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:pay</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="3"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>De forma a utilizá-lo num esquema de <code>Ecto</code> da seguinte forma:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">User.Action</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">  <span style="color: #9d79d6;">use</span> <span style="color: #7ad5d6;">Ecto.Schema</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4">  <span style="color: #86abdc;">schema</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;users_actions&quot;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="5">    <span style="color: #86abdc;">belongs_to</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:user</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7">    <span style="color: #86abdc;">field</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:action</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">User.Action.Type</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="8">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="9"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>E caso queiramos lidar com átomos ao nível da aplicação mas serializá-los enquanto números inteiros, que possamos definir o mesmo tipo como:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">User.Action.Type</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">  <span style="color: #9d79d6;">use</span> <span style="color: #7ad5d6;">TypedEnum</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">values: </span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">bid: </span><span style="color: #f4a261;">0</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">request: </span><span style="color: #f4a261;">1</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">upload: </span><span style="color: #f4a261;">2</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">pay: </span><span style="color: #f4a261;">3</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="3"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Vejamos então uma lista do que o nosso módulo necessita suportar:</p>
<ul>
<li class="sub-li">a macro <span class="since">__using__</span>, de forma que os módulos que queiram fazer uso dele, possam utilizar a palavra-chave <span class="since">use</span>, como demonstrado nos exemplos do que queremos</li>
<li class="sub-li">que seja capaz de distinguir entre listas de átomos como valores válidos e listas de palavras-chaves, de forma a que possa intuitivamente implementar ora versões com base de número inteiro, ou de listagramas</li>
<li class="sub-li">permitir a quem o deseje implementar a possibilidade de escrever funções adicionais para <span class="since">cast</span>/<span class="since">dump</span> do comportamento <span class="since">Ecto.Type</span></li>
<li class="sub-li">introduzir automaticamente um <span class="since">typespec</span> (especificação de tipo) que reflita todos os valores válidos na sua forma de átomo</li>
<li class="sub-li">que emerja erros aquando da compilação quando os valores utilizados na definição do tipo sejam inválidos</li>
</ul>
<p>Dito isso, o nosso módulo final terá a seguinte forma:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1">
</div><div class="line" data-line="2"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">TypedEnum</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="3">  <span style="color: #9d79d6;">defmacro</span> <span style="color: #86abdc;">__before_compile__</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_env</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="4">    <span style="color: #738091;"># these are inserted in the before_compile hook to give opportunity to the</span>
</div><div class="line" data-line="5">    <span style="color: #738091;"># implementing module to define additional variations</span>
</div><div class="line" data-line="6">    <span style="color: #9d79d6;">quote</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="7">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:error</span>
</div><div class="line" data-line="8">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:error</span>
</div><div class="line" data-line="9">      <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #dfdfe0;">data</span>
</div><div class="line" data-line="10">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="11">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="12">
</div><div class="line" data-line="13">  <span style="color: #9d79d6;">defmacro</span> <span style="color: #86abdc;">__using__</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">opts</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="14">    <span style="color: #dfdfe0;">values</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Keyword</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">fetch!</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">opts</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:values</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="15">    <span style="color: #dfdfe0;">mod</span> <span style="color: #aeafb0;">=</span> <span style="color: #f6b079;">__CALLER__</span><span style="color: #aeafb0;">.</span><span style="color: #dfdfe0;">module</span>
</div><div class="line" data-line="16">
</div><div class="line" data-line="17">    <span style="color: #dfdfe0;">is_int_enum?</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Keyword</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">keyword?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="18">
</div><div class="line" data-line="19">    <span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">is_int_enum?</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="20">      <span style="color: #f4a261;">true</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="21">        <span style="color: #86abdc;">:ok</span> <span style="color: #aeafb0;">=</span> <span style="color: #86abdc;">validate_int_enum</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="22">        <span style="color: #86abdc;">bind_as_integer_version</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="23">
</div><div class="line" data-line="24">      <span style="color: #f4a261;">false</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="25">        <span style="color: #86abdc;">:ok</span> <span style="color: #aeafb0;">=</span> <span style="color: #86abdc;">validate_string_enum</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="26">        <span style="color: #86abdc;">bind_as_stringed_version</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="27">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="28">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="29">
</div><div class="line" data-line="30">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">validate_int_enum</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="31">    <span style="color: #9d79d6;">with</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">true</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">&lt;-</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:length</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">length</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">&gt;</span> <span style="color: #f4a261;">0</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="32">         <span style="color: #aeafb0;">&lbrace;</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">true</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">&lt;-</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:format</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">all?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #86abdc;">valid_int_enum?</span><span style="color: #aeafb0;">/</span><span style="color: #aeafb0;">1</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="33">      <span style="color: #86abdc;">:ok</span>
</div><div class="line" data-line="34">    <span style="color: #9d79d6;">else</span>
</div><div class="line" data-line="35">        <span style="color: #dfdfe0;">error</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #86abdc;">raise_error</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">error</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="36">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="37">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="38">
</div><div class="line" data-line="39">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">validate_string_enum</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="40">    <span style="color: #9d79d6;">with</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">true</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">&lt;-</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:length</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">length</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">&gt;</span> <span style="color: #f4a261;">0</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="41">         <span style="color: #aeafb0;">&lbrace;</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">true</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">&lt;-</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:format</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">all?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">/</span><span style="color: #aeafb0;">1</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="42">      <span style="color: #86abdc;">:ok</span>
</div><div class="line" data-line="43">    <span style="color: #9d79d6;">else</span>
</div><div class="line" data-line="44">        <span style="color: #dfdfe0;">error</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #86abdc;">raise_error</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">error</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="45">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="46">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="47">
</div><div class="line" data-line="48">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">valid_int_enum?</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">k</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">v</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="49">    <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">k</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #86abdc;">is_integer</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">v</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="50">
</div><div class="line" data-line="51">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">raise_error</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:length</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="52">    <span style="color: #86abdc;">do: </span><span style="color: #9d79d6;">raise</span> <span style="color: #81b29a;">&quot;TypedEnum expects `:values` to be a list or keyword list with at least 1 element&quot;</span>
</div><div class="line" data-line="53">
</div><div class="line" data-line="54">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">raise_error</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:format</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="55">    <span style="color: #86abdc;">do: </span><span style="color: #9d79d6;">raise</span> <span style="color: #81b29a;">&quot;TypedEnum expects the format of `:values` to be a keywordlist with the atom version as the key and an integer as the value (e.g.: [atom_key: 1, another_possible: 2, ...]), or a list of atoms for the string enum version (e.g.: [:atom_key, :another_possible, ...])&quot;</span>
</div><div class="line" data-line="56">
</div><div class="line" data-line="57">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">bind_as_integer_version</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="58">    <span style="color: #9d79d6;">quote</span> <span style="color: #86abdc;">bind_quoted: </span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">atoms_ints: </span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">mod: </span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">]</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="59">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">before_compile </span><span style="color: #7ad5d6;">TypedEnum</span>
</div><div class="line" data-line="60">
</div><div class="line" data-line="61">      <span style="color: #dfdfe0;">atom_integer_map</span> <span style="color: #aeafb0;">=</span>
</div><div class="line" data-line="62">        <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="63">          <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="64">        <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="65">
</div><div class="line" data-line="66">      <span style="color: #dfdfe0;">string_integer_map</span> <span style="color: #aeafb0;">=</span>
</div><div class="line" data-line="67">        <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atom_integer_map</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="68">          <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Atom</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_string</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="69">        <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="70">
</div><div class="line" data-line="71">      <span style="color: #dfdfe0;">string_atom_map</span> <span style="color: #aeafb0;">=</span>
</div><div class="line" data-line="72">        <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="73">          <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Atom</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_string</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="74">        <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="75">
</div><div class="line" data-line="76">      <span style="color: #dfdfe0;">integer_atom_map</span> <span style="color: #aeafb0;">=</span>
</div><div class="line" data-line="77">        <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="78">          <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="79">        <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="80">
</div><div class="line" data-line="81">      <span style="color: #dfdfe0;">strings</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">map</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #7ad5d6;">Atom</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_string</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="82">      <span style="color: #dfdfe0;">atoms</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">map</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #dfdfe0;">atom_val</span> <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="83">      <span style="color: #dfdfe0;">ints</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">map</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #dfdfe0;">int</span> <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="84">
</div><div class="line" data-line="85">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">behaviour </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="86">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="87">      <span style="color: #9d79d6;">def</span> <span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:integer</span>
</div><div class="line" data-line="88">
</div><div class="line" data-line="89">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:valid_atoms</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="90">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:valid_strings</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="91">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:valid_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">ints</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="92">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:validation_mappings</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">string_atom_map</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="93">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:validation_mappings_atoms</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">atom_integer_map</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="94">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:validation_mappings_strings</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">string_integer_map</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="95">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:validation_mappings_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">integer_atom_map</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="96">
</div><div class="line" data-line="97">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">type </span><span style="color: #86abdc;">t</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">::</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reverse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:|</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&amp;</span><span style="color: #aeafb0;">1</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #aeafb0;">2</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="98">
</div><div class="line" data-line="99">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">spec </span><span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:atoms</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">:strings</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">:ints</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">::</span> <span style="color: #86abdc;">list</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">t</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">list</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">String</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">t</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">list</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">integer</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="100">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">&quot;Given a desired format returns the matching values for that format&quot;</span>
</div><div class="line" data-line="101">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">type</span> <span style="color: #aeafb0;">\\</span> <span style="color: #86abdc;">:atoms</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="102">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:ints</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ints</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="103">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="104">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:strings</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="105">
</div><div class="line" data-line="106">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="107">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">load</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="108">
</div><div class="line" data-line="109">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="110">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="111">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="112">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="113">
</div><div class="line" data-line="114">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="115">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="116">
</div><div class="line" data-line="117">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_integer</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ints</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="118">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings_ints</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="119">
</div><div class="line" data-line="120">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="121">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="122">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="123">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings_atoms</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="124">
</div><div class="line" data-line="125">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="126">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings_strings</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="127">
</div><div class="line" data-line="128">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_integer</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ints</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="129">
</div><div class="line" data-line="130">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">&quot;Dumps but raises in case of non-valid data&quot;</span>
</div><div class="line" data-line="131">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump!</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="132">        <span style="color: #9d79d6;">case</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="133">          <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">value</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="134">            <span style="color: #dfdfe0;">value</span>
</div><div class="line" data-line="135">
</div><div class="line" data-line="136">          <span style="color: #738091;">_</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="137">            <span style="color: #9d79d6;">raise</span> <span style="color: #7ad5d6;">Ecto.CastError</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="138">              <span style="color: #86abdc;">message: </span><span style="color: #81b29a;">&quot;Unable to dump:: </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;"> ::into:: </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span><span style="color: #aeafb0;">(</span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="139">              <span style="color: #86abdc;">type: </span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="140">              <span style="color: #86abdc;">value: </span><span style="color: #dfdfe0;">data</span>
</div><div class="line" data-line="141">        <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="142">      <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="143">
</div><div class="line" data-line="144">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="145">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="146">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">embed_as</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:dump</span>
</div><div class="line" data-line="147">
</div><div class="line" data-line="148">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="149">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="150">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">equal?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">term_1</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">term_1</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #f4a261;">true</span>
</div><div class="line" data-line="151">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">equal?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">term_1</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">term_2</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">term_1</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">==</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">term_2</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="152">
</div><div class="line" data-line="153">      <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="154">        <span style="color: #86abdc;">do: </span><span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings_atoms</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="155">
</div><div class="line" data-line="156">      <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="157">        <span style="color: #86abdc;">do: </span><span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings_strings</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="158">
</div><div class="line" data-line="159">      <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_integer</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ints</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="160">        <span style="color: #86abdc;">do: </span><span style="color: #dfdfe0;">data</span>
</div><div class="line" data-line="161">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="162">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="163">
</div><div class="line" data-line="164">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">bind_as_stringed_version</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="165">    <span style="color: #9d79d6;">quote</span> <span style="color: #86abdc;">bind_quoted: </span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">atoms: </span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">mod: </span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">]</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="166">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">before_compile </span><span style="color: #7ad5d6;">TypedEnum</span>
</div><div class="line" data-line="167">
</div><div class="line" data-line="168">      <span style="color: #dfdfe0;">strings</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">map</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #dfdfe0;">entry</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #7ad5d6;">Atom</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_string</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">entry</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="169">      <span style="color: #dfdfe0;">mapped</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">zip</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">|&gt;</span> <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">into</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="170">
</div><div class="line" data-line="171">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">behaviour </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="172">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="173">      <span style="color: #9d79d6;">def</span> <span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:string</span>
</div><div class="line" data-line="174">
</div><div class="line" data-line="175">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:valid_atoms</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="176">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:valid_strings</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="177">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:validation_mappings</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">mapped</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="178">
</div><div class="line" data-line="179">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">type </span><span style="color: #86abdc;">t</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">::</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reverse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:|</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&amp;</span><span style="color: #aeafb0;">1</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #aeafb0;">2</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="180">
</div><div class="line" data-line="181">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">spec </span><span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:atoms</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">:strings</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">::</span> <span style="color: #86abdc;">list</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">t</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">list</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">String</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">t</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="182">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">type</span> <span style="color: #aeafb0;">\\</span> <span style="color: #86abdc;">:atoms</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="183">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="184">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:strings</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="185">
</div><div class="line" data-line="186">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="187">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">load</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="188">
</div><div class="line" data-line="189">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="190">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="191">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="192">
</div><div class="line" data-line="193">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="194">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">String</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="195">
</div><div class="line" data-line="196">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="197">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="198">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="199">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Atom</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_string</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="200">
</div><div class="line" data-line="201">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="202">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="203">
</div><div class="line" data-line="204">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">&quot;Dumps but raises in case of non-valid data&quot;</span>
</div><div class="line" data-line="205">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump!</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="206">        <span style="color: #9d79d6;">case</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="207">          <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">value</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="208">            <span style="color: #dfdfe0;">value</span>
</div><div class="line" data-line="209">
</div><div class="line" data-line="210">          <span style="color: #738091;">_</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="211">            <span style="color: #9d79d6;">raise</span> <span style="color: #7ad5d6;">Ecto.CastError</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="212">              <span style="color: #86abdc;">message: </span><span style="color: #81b29a;">&quot;Unable to dump:: </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;"> ::into:: </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span><span style="color: #aeafb0;">(</span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="213">              <span style="color: #86abdc;">type: </span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="214">              <span style="color: #86abdc;">value: </span><span style="color: #dfdfe0;">data</span>
</div><div class="line" data-line="215">        <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="216">      <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="217">
</div><div class="line" data-line="218">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="219">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="220">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">embed_as</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:dump</span>
</div><div class="line" data-line="221">
</div><div class="line" data-line="222">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="223">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="224">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">equal?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">term_1</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">term_1</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #f4a261;">true</span>
</div><div class="line" data-line="225">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">equal?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">term_1</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">term_2</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">term_1</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">==</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">term_2</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="226">
</div><div class="line" data-line="227">      <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="228">        <span style="color: #86abdc;">do: </span><span style="color: #dfdfe0;">data</span>
</div><div class="line" data-line="229">
</div><div class="line" data-line="230">      <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="231">        <span style="color: #86abdc;">do: </span><span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="232">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="233">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="234"><span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="235">
</div></code></pre>
<p>Para que quem queira utilizar esta macro tenha a possibilidade de incluir também cláusulas específicas para <code>cast/dump/get_term</code>, definimos uma macro especial, <code>__before_compile__</code> que nos permite inserir código após o módulo ter sido compilado, mas antes da compilação ser dada como finalizada. Neste caso, através disso incluímos versões das funções <code>load/dump/get_term</code> que funcionam para quaisquer valores não válidos e resolve no átomo <code>:error</code> (que é o esperado pelo <code>Ecto</code> quando um valor não é válido).</p>
<p>Uma vez que a função <code>load/1</code> simplesmente executa a função <code>cast/1</code> não há necessidade de definir uma versão de erro para ela.</p>
<p>A, também especial, macro <code>__using__</code>:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1">  <span style="color: #9d79d6;">defmacro</span> <span style="color: #86abdc;">__using__</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">opts</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">    <span style="color: #dfdfe0;">values</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Keyword</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">fetch!</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">opts</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:values</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="3">    <span style="color: #dfdfe0;">mod</span> <span style="color: #aeafb0;">=</span> <span style="color: #f6b079;">__CALLER__</span><span style="color: #aeafb0;">.</span><span style="color: #dfdfe0;">module</span>
</div><div class="line" data-line="4">
</div><div class="line" data-line="5">    <span style="color: #dfdfe0;">is_int_enum?</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Keyword</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">keyword?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7">    <span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">is_int_enum?</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="8">      <span style="color: #f4a261;">true</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="9">        <span style="color: #86abdc;">:ok</span> <span style="color: #aeafb0;">=</span> <span style="color: #86abdc;">validate_int_enum</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="10">        <span style="color: #86abdc;">bind_as_integer_version</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="11">
</div><div class="line" data-line="12">      <span style="color: #f4a261;">false</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="13">        <span style="color: #86abdc;">:ok</span> <span style="color: #aeafb0;">=</span> <span style="color: #86abdc;">validate_string_enum</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="14">        <span style="color: #86abdc;">bind_as_stringed_version</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="15">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="16">  <span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Uma vez que é uma macro, irá ser avaliada aquando da compilação do código. Nela, utilizamos <code>Keyword.fetch!</code> para o termo <code>:values</code> das opções que forem passadas ao <code>use</code>, por exemplo <code>use TypedEnum, values: [:bid, :request, :upload, :pay]</code> significa que a variável <code>opts</code> será uma lista <code>Keyword</code> com uma chave <code>:values</code>, cujo valor será uma lista de átomos (<code>:bid</code>, <code>:request</code>, etc). Uma vez que a chave <code>:values</code> é essencial ao funcionamento da macro, caso não esteja presente nas <code>opts</code> queremos que surja um erro, e daí utilizarmos <code>fetch!</code>.</p>
<p>De seguida decidimos se devemos definir o enumerador com valores de números inteiros ou listagramas, e fazemo-lo avaliando a forma do valor da chave <code>:values</code>. Caso seja uma lista <code>Keyword</code> assumimos que seja números inteiros, pois será composta por pares de <code>versão_átomo -&gt; número_inteiro_correspondente</code>. Caso seja uma simples lista de átomos, assumimos que o desejado é que o enumerador use listagramas como formato.</p>
<p>Dependendo disso fazemos algumas verificações para nos certificarmos que os valores têm o formato correcto. Tudo isto acontece aquando da compilação, logo qualquer erro que haja emergirá nessa altura, o que permite ao utilizador saber imediatamente se há algum problema.</p>
<p>Agora iremos fazer uma leitura do que acontece na versão com base em números inteiros. Visto ser mais complexa que a com base em listagramas acredito que compreendendo esta será fácil ler a outra. Sendo uma macro que utiliza <code>quote</code>, os conteúdos dos blocos de <code>quote do end</code> irão ser introduzidos nos módulos que utilizarem esta macro e é o que se passa nesses blocos que é o mais importante.</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">bind_as_integer_version</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">    <span style="color: #9d79d6;">quote</span> <span style="color: #86abdc;">bind_quoted: </span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">atoms_ints: </span><span style="color: #dfdfe0;">values</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">mod: </span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">]</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="3">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">before_compile </span><span style="color: #7ad5d6;">TypedEnum</span>
</div><div class="line" data-line="4">
</div><div class="line" data-line="5">      <span style="color: #dfdfe0;">atom_integer_map</span> <span style="color: #aeafb0;">=</span>
</div><div class="line" data-line="6">        <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="7">          <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="8">        <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="9">
</div><div class="line" data-line="10">      <span style="color: #dfdfe0;">string_integer_map</span> <span style="color: #aeafb0;">=</span>
</div><div class="line" data-line="11">        <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atom_integer_map</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="12">          <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Atom</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_string</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="13">        <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="14">
</div><div class="line" data-line="15">      <span style="color: #dfdfe0;">string_atom_map</span> <span style="color: #aeafb0;">=</span>
</div><div class="line" data-line="16">        <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="17">          <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Atom</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_string</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="18">        <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="19">
</div><div class="line" data-line="20">      <span style="color: #dfdfe0;">integer_atom_map</span> <span style="color: #aeafb0;">=</span>
</div><div class="line" data-line="21">        <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="22">          <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="23">        <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="24">
</div><div class="line" data-line="25">      <span style="color: #dfdfe0;">strings</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">map</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #7ad5d6;">Atom</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_string</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="26">      <span style="color: #dfdfe0;">atoms</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">map</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">atom_val</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #dfdfe0;">atom_val</span> <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="27">      <span style="color: #dfdfe0;">ints</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">map</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">int</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #dfdfe0;">int</span> <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="28">
</div><div class="line" data-line="29">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">behaviour </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="30">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="31">      <span style="color: #9d79d6;">def</span> <span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:integer</span>
</div><div class="line" data-line="32">
</div><div class="line" data-line="33">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:valid_atoms</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="34">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:valid_strings</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="35">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:valid_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">ints</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="36">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:validation_mappings</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">string_atom_map</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="37">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:validation_mappings_atoms</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">atom_integer_map</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="38">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:validation_mappings_strings</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">string_integer_map</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="39">      <span style="color: #7ad5d6;">Module</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put_attribute</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:validation_mappings_ints</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">integer_atom_map</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="40">
</div><div class="line" data-line="41">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">type </span><span style="color: #86abdc;">t</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">::</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reverse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:|</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&amp;</span><span style="color: #aeafb0;">1</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #aeafb0;">2</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="42">
</div><div class="line" data-line="43">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">spec </span><span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:atoms</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">:strings</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">:ints</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">::</span> <span style="color: #86abdc;">list</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">t</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">list</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">String</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">t</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">list</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">integer</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="44">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">&quot;Given a desired format returns the matching values for that format&quot;</span>
</div><div class="line" data-line="45">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">type</span> <span style="color: #aeafb0;">\\</span> <span style="color: #86abdc;">:atoms</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="46">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:ints</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ints</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="47">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="48">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:strings</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="49">
</div><div class="line" data-line="50">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="51">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">load</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="52">
</div><div class="line" data-line="53">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="54">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="55">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="56">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="57">
</div><div class="line" data-line="58">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="59">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="60">
</div><div class="line" data-line="61">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_integer</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ints</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="62">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings_ints</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="63">
</div><div class="line" data-line="64">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="65">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="66">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="67">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings_atoms</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="68">
</div><div class="line" data-line="69">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="70">        <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings_strings</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="71">
</div><div class="line" data-line="72">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_integer</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ints</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="73">
</div><div class="line" data-line="74">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">&quot;Dumps but raises in case of non-valid data&quot;</span>
</div><div class="line" data-line="75">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump!</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="76">        <span style="color: #9d79d6;">case</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="77">          <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">value</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="78">.            <span style="color: #dfdfe0;">value</span>
</div><div class="line" data-line="79">
</div><div class="line" data-line="80">          <span style="color: #738091;">_</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="81">            <span style="color: #9d79d6;">raise</span> <span style="color: #7ad5d6;">Ecto.CastError</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="82">              <span style="color: #86abdc;">message: </span><span style="color: #81b29a;">&quot;Unable to dump:: </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;"> ::into:: </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span><span style="color: #aeafb0;">(</span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="83">              <span style="color: #86abdc;">type: </span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">mod</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="84">              <span style="color: #86abdc;">value: </span><span style="color: #dfdfe0;">data</span>
</div><div class="line" data-line="85">        <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="86">      <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="87">
</div><div class="line" data-line="88">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="89">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="90">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">embed_as</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:dump</span>
</div><div class="line" data-line="91">
</div><div class="line" data-line="92">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #7ad5d6;">Ecto.Type</span>
</div><div class="line" data-line="93">      <span style="color: #738091;">@</span><span style="color: #738091;">doc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="94">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">equal?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">term_1</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">term_1</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #f4a261;">true</span>
</div><div class="line" data-line="95">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">equal?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">term_1</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">term_2</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">term_1</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">==</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">term_2</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="96">
</div><div class="line" data-line="97">      <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atoms</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="98">        <span style="color: #86abdc;">do: </span><span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings_atoms</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="99">
</div><div class="line" data-line="100">      <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">strings</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="101">        <span style="color: #86abdc;">do: </span><span style="color: #f6b079;">@</span><span style="color: #f6b079;">validation_mappings_strings</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="102">
</div><div class="line" data-line="103">      <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_integer</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">and</span> <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">in</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ints</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="104">        <span style="color: #86abdc;">do: </span><span style="color: #dfdfe0;">data</span>
</div><div class="line" data-line="105">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="106">  <span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Neste bloco de <code>quote</code> usamos o atributo <code>bind_quoted</code>, que nos permite passar variáveis propriamente expandidas para serem utilizadas no interior do bloco. Neste caso, <code>atoms_ints</code> com os valores contidos em <code>values</code> (o que havia sido passado como chave <code>:values</code> à macro), e também <code>mod</code>, contendo o nome do módulo que executou a macro.</p>
<p>Primeiro incluímos imediatamente o atributo <code>@before_compile</code>, que faz com que após a compilação, mas antes da sua finalização, a macro <code>__before_compile__</code> do módulo em questão seja executada, nesta caso o <code>__before_compile__/1</code> do módulo <code>TypedEnum</code>. Depois utilizamos a lista de <code>Keyword</code>s (<code>atoms_ints</code>) para gerar um conjunto de mapas e listas que nos auxiliarão a decidir que validações e transformações são necessárias quando as funções de comportamento <code>Ecto.Type</code> sejam executadas.</p>
<p>Dessa lista de <code>values</code>, geramos 4 mapas - se utilizarmos o exemplo anterior onde a chave <code>:values</code> assumia o valor de uma lista com a seguinte forma <code>[val_1: 1, val_2: 2]</code>), o resultado de <code>atom_integer_map</code>, <code>string_integer_map</code>, <code>string_atom_map</code>, <code>integer_atom_map</code> será respectivamente:</p>
<ul>
<li class="sub-li">mapa com as mesmas chaves e valores que a lista <span class="since">Keyword</span>, neste caso: <span class="since">%{val_1: 1, ...}</span></li>
<li class="sub-li">outro mapa idêntico mas agora com as chaves em formato de listagrama ao invés de átomos: <span class="since">%{"val_1" => 1, ...}</span></li>
<li class="sub-li">um mapa que mapeia as correspondências entre listagramas e versões em átomos: <span class="since">%{"val_1" => :val_1, ...}</span></li>
<li class="sub-li">por último, as correspondências entre números inteiros e as suas equivalências em formato de átomo, e.g: <span class="since">%{1 => :val_1, ...}</span></li>
</ul>
<p>Com estes quatro mapas auxiliares será mais fácil resolvermos os valores do tipo dependendo se estamos a fazer uma validação/transformação (<code>cast/1</code>) ou uma serialização (<code>dump/1</code>), e tendo em conta o formato do termo original (n. inteiro, listagrama ou átomo).</p>
<p>De seguida geramos 3 listas adicionais, que nos facilitarão restringir as cláusulas das nossas funções:</p>
<ul>
<li class="sub-li">para listagramas: <span class="since">["val_1", ...]</span></li>
<li class="sub-li">para átomos: <span class="since">[:val_1, ...]</span></li>
<li class="sub-li">para números inteiros: <span class="since">[1, ...]</span></li>
</ul>
<p>Colocamos todas estas variáveis auxiliares em atributos do módulo (o que significa que quem esteja a utilizar o mesmo, os pode aceder com a síntaxe usual, <code>@nome_do_atributo</code>), e utilizamos a lista de valores válidos nos seus diferentes formatos para providenciar uma função, <code>values/1</code>, que resolve em todos os valores válidos para o formato desejado.</p>
<p>As funções <code>cast</code> (e no nosso caso <code>load</code> também), são usadas para transformar termos do seu formato interno na base de dados, ou externos à nossa aplicação, no formato utilizado pela nossa aplicação, neste caso em átomos. Por conseguinte, se parte do código por algum motivo executar <code>load/cast</code> com valores já no formato correcto, a resolução dessas funções resultará no mesmo termo. Se no entanto utilizarmos termos no formato de listagramas ou números inteiros, se tiverem uma correspondência válida, serão convertidos no seu formato de átomo. Caso sejam inválidos emergirão um erro.</p>
<p>No caso da função <code>dump</code>, a lógica é em tudo semelhante, com a diferença que o formato final que procuramos é o de número inteiro (para serialização na base de dados), neste caso, listagramas e átomos, se tiverem uma correspondência válida, serão convertidos no seu formato de número inteiro, caso o termo a avaliar seja já um número inteiro e válido, a função resolverá com esse mesmo termo.</p>
<p>Uma vez que cada função <code>load/1</code> e <code>dump/1</code> tem a acompanhar um grupo de restrições, caso os valores passados não sejam válidos, as cláusulas que inserimos através do <code>@before_hook</code> serão as executadas (uma vez que aceitam qualquer termo e não têm guardas), e resultarão num erro.</p>
<p>Caso o utilizador do módulo, tenha adicionado cláusulas extra, devido à ordem final de todas elas no módulo compilado, essas serão tentativamente executadas antes das dos erros. Por exemplo, imaginemos que estamos a programar uma aplicação que necessita interagir com uma versão antiga da base de dados, em que ao invés de utilizarem o termo <code>&quot;val_1&quot;</code>, estavam a utilizar o termo <code>&quot;valor_1&quot;</code>. Actualmente <code>&quot;valor_1&quot;</code> já não é uma representação válida, por isso não queremos permitir que seja persistida pelo nosso sistema, mas ao mesmo tempo, tendo uma correspondência directa ao termo <code>&quot;val_1&quot;</code> que por sua vez é válido, queremos convertê-la caso ela surja como parâmetro em alguma situação.</p>
<p>Nesse caso poderiamos definir o nosso tipo da seguinte forma:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">ExampleCallerModule</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">  <span style="color: #9d79d6;">use</span> <span style="color: #7ad5d6;">TypedEnum</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">values: </span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">val_1: </span><span style="color: #f4a261;">1</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">val_2: </span><span style="color: #f4a261;">2</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">cast</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;valor_1&quot;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:val_1</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="5">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">dump</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;valor_1&quot;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">1</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="6">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">get_term</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;valor_1&quot;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:val_1</span>
</div><div class="line" data-line="7"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>E isto permitir-nos-ia validar, traduzir e verificar a sua equivalência, sem no entanto necessitar de introduzir mais um item no enumerador, ou complicar significativamente o nosso programa de forma a suportar tal caso.</p>
<p>Adicionalmente às funções requeridas pelo comportamento <code>Ecto.Type</code> eu pessoalmente gosto de definir também uma <code>dump!/1</code>, que simplesmente executa a <code>dump/1</code> normal, e caso a resolução seja qualquer outra coisa que uma tupla <code>&lbrace;:ok, _&rbrace;</code>, que emerja um erro.</p>
<p>A função <code>get_term</code> é simplesmente para facilitar a verificação de equivalência entre termos.</p>
<p>E isto é basicamente tudo o que é necessario. A versão em listagramas é em todo símile a esta, mas mais simples uma vez que apenas necessita de funcionar com átomos e listagramas.</p>
<p>Como última nota relativa ao módulo que escrevemos, optei por manter duas versões separadas para a versão listagrama e outra para a versão de números inteiros - isto porque apesar de haver partes duplicadas entre ambas, escrever apenas uma versão requereria uso de várias condicionais, e penso que o código resultante seria bem mais complicado e não linear de entender. Assim temos um pouco de duplicação mas cada parte trata apenas do que tem a tratar.</p>
<p>E agora que vemos como poderíamos implementar tal módulo para nos auxiliar, caso queiram podem utilizar um pacote já feito, disponível em <a href="https://hexdocs.pm/typed_enum/TypedEnum.html">hexdocs</a> (ou github <a href="https://github.com/mnussbaumer/typed_enum">mnussbaumer/typed_enum</a>. De qualquer das formas espero que tenha sido útil.</p> ]]></description>
    </item>
    <item>
       <title>What&#39;s wrong with Software Development</title>
       <link>https://micaelnussbaumer.com/posts/what-s-wrong-with-software-development</link>
       <pubDate>Tue, 16 Nov 2021 01:00:00 +07</pubDate>
       <guid>https://micaelnussbaumer.com/posts/what-s-wrong-with-software-development</guid>
       <description><![CDATA[ <p><span class="since">(Addendum 2026-03-14:</span> This was written before the current AI cycle but funnily, it seems, most of these things turned out, or are turning out, to be also important for Agentic coding, which is kinda poetic...<span class="since">)</span></p>
<hr class="hr-separator-b">
<p>As someone who writes code for most of my time, either as my work or in personal projects I find it extremely difficult to understand the lacking of proper written documents describing what should be accomplished and the reluctance in using the written format to discuss and <code>document the development of software</code>.</p>
<p>First let's go through what I called <code>&quot;written documents&quot;</code>. There are different forms these can assume, in common they have that they specify to varying degrees of detail, technicality, and/or context the purpose, specifications, and requirements of a given piece of <code>&quot;software idea&quot;</code>.</p>
<p>I call it <code>&quot;software idea&quot;</code>, because that's what most things are until they're fully materialized as <code>&quot;working software&quot;</code>.</p>
<p>Some of the more common documents (or artefacts) that concern this are:</p>
<ul>
  <li class="reg-li">- Written Specifications:</li>
  <li class="sub-li">Document(s) detailing, usually with high attention to technical capabilities, restrictions or requirements, in an unambiguous language, the working of an intended software program</li>
  <li class="reg-li">- User Stories:</li>
  <li class="sub-li">Written documents detailing at a high level the intended functionality of a software program/capability, from the point of view of a user of the software interfaces</li>
  <li class="reg-li">- Design Documents:</li>
  <li class="sub-li">- Visual document, either in the form of diagrams, and/or actual illustrations of the intended software</li>
</ul>
<p>There's probably more ways, or specific terms to specify what a system, functionality, or capability is to achieve, both in itself or when in bigger existing system (when it's not self-contained) but these cover most of the &quot;ideas&quot;.</p>
<p>I don't expect everybody (including myself) to master all these forms of laying out projects, in all contexts and all situations. If I'm working with someone who <code>is not</code> a software developer and just wants a website that does X, I know for sure I will have to weight in my own knowledge, and do extra work to get into the details of what is wanted and access its feasibility. It's normal in these cases to have to go from simple <code>user stories</code>, and it's expected that you as the developer will take care of the technicalities related to implementing them.</p>
<p>If I'm working through a <code>Project Manager (PM)</code> then my expectations change a little bit. I'm no longer working with someone that simply wants an idea converted into software, but instead someone that, as the title implies, is responsible for managing a project, and as such I expect them to have both technical knowledge and to dedicate part of their time producing more relevant and accurate documents detailing what is to be implemented. Again, it's not reasonable to expect that a <code>PM</code> will know in all details both the underlying technology and any and all roadblocks, but it's normal to expect a well rounded specification and at least some understanding of the system, languages and platforms in use. This last part is relevant and I'll touch on it later on.</p>
<hr class="hr-separator-b">
<p>We'll focus more on the software being developed with a <code>PM</code>, since the other cases are in themselves a bit off-target when discussing the need for documentation and written artefacts besides the code. Most projects, even small ones, will usually have a <code>PM</code> that is in charge of overseeing the implementation of whatever is to be built.</p>
<p>Let me start by prefacing that I understand that a <code>PM</code> has a non trivial amount of things to worry about - managing bikeshedding, going through discussions full of cruft, making sure development is aligned with upper goals, making sure it's on track, solving issues, allocating resources and making technical decisions. Let me also add, that although I don't claim that I would do their work better than they do, their work is their work and not mine.
If I was to be hired or paid to both oversee and develop (i.e. code), then my compensation needs to take that into account and in case it does, I will be more than happy to take on additional responsibilities. If on the other hand my compensation doesn't have equity and is priced at a time unit, then I don't think it's reasonable to expect me to take on additionaly responsibility that someone else is being paid to be responsible for. As with software, good separation of concerns is important. I will do my best nonetheless, but if your advice, suggestions and observations are continuously ignored irrespective of their value (either immediate or solving a problem that manifests itself later on) at some point you just don't do that anymore.</p>
<p>The same if after careful consideration, and even spending <code>&quot;non-billable&quot;</code> time on a problem, your work is rejected and replaced with some dim-wit solution that <code>&quot;is simpler&quot;</code>, and discards all the knowledge you had gathered while solving it (here I'm not saying in the sense of being attached to the code you write, there's certainly cases where you come up with a solution that is more complex than it needs to be and it's welcomed in that case that a <code>PM or team mate rejects it</code>, it's part of their work and part of being in a team, I'm refering to ditching something for something else that has problems from the get-go, not only imaginary future problems).</p>
<p>So it's in this situation, working with a <code>PM</code>, that the reluctance in requiring and expecting written artefacts to be produced becomes interesting.
In a way I would expect, and if I work as a <code>PM</code> would require, that documentation (discussions, specifications, guides, how-to's related to the project, etc) AND tests are something fundamental. As a <code>PM</code> I can't think of any other way of keeping up with how everything works, how everything is <code>SUPPOSED</code> to work, and how we got into this given place.</p>
<p>People insist on doing video/call based meetings where the &quot;team&quot; catches up and courses of action are decided. This is ok to do, and there might be a need to even have these outside of pure business/development concerns (as team building rituals not concerned with specific work related issues) but it can't replace written documentation.</p>
<p>Folks whine about tacit knowledge but then don't take any action to solve it which, guess what, can only be solved with written documentation.
People will prefer re-writing a completely correctly implemented solutions, with all the costs that entails, because there's no one that knows how it works.
PM's end up having no frigging clue of how the project they're managing works, is tied (or glued) together, all because they can't be bothered to go through more than 1 paragraph of text.</p>
<hr class="hr-separator-b">
<p>Here I will add, that developers are some times actively part of the problem as well. The <code>PM's</code> work is nonetheless making sure this is taken care of, not making it normal though. We can put in the list of developer-made problems, the unwillingness to learn specifics outside their area of comfort. Examples can be something that is written in a language that they don't have as much familiarity with. You sometimes see perfectly valid, tested, extensible code, be replaced by orders of magnitude more complexity, untested, brittle layers, just for the sake of sidestepping having to learn how something is being accomplished with much less. No documentation, no testing, no how-to's for getting pieces of a system working, etc. Although these are all problems a developer contributes too, the role of the <code>PM</code> should be to make sure these things are required and properly budgeted. At least for me, it's fairly easier to document something as I'm writing it as opposed to after the fact.</p>
<p>This lack of <code>written documentation</code> (or performative documentation, such as tests - in the sense that it performs work to assert the validity of its contents) then exacerbates the issues with keeping up with how things work, if they should be working, and having a complete view of a system. On top of that, it makes <code>on-boarding</code> fairly more difficult as one can't for the most part just go on <code>&quot;discoverability&quot;</code> mode and instead has to rely on lower level code to gather what the <code>&quot;systems&quot;</code> should be doing. It's also fairly more difficult to access if a system is complex because of the domain it covers or if because it's being wrongly thought about.</p>
<p>Things such as <code>refactoring</code> become a <code>painful</code> chore, because, why would you try to refactor something when you don't even have a baseline of expected functionality asserted? Or at least something explaining what that functionality is expected to do?
So if it's not product breaking it just gets pushed to the <code>&quot;backlog&quot;</code> void. If it's product breaking then all the required (like, big picture at least) tests to make sure the refactoring conforms have to be written - probably by someone who didn't write the initial implementation, doesn't have all the context, nor knows many of the pitfalls encountered during development because, you guessed it, there's no documentation.</p>
<p>Then, when the backlog void threatens to suck up the whole thing, the solution is to re-write. On top of this you might also have developers just deciding to quit or unable to have any semblance of productivity.</p>
<p>So when people go about how they don't have budget for documentation, testing, to put effort into making your software understandable what they're actually saying is they don't care at all for the costs of developing software. Sometimes this makes sense, again, if it's a online freelancing gig for a test-the-waters website, sure, go ahead - it might not even work so those costs would all be extra. But even in those situations, if the software is expected to have some modicum of complexity, tests and documentation will inevitably pay themselves in anything running for more than 2 months, or when you have to have another developer picking up from the existing work.</p>
<hr class="hr-separator-b">
<p>What is really mind-boggling is that having documentation and written word as first-class artefacts in a project as the baseline helps beyond these directly related issues already mentioned.</p>
<p>Jobs will have descriptions such as &quot;employee budget for improvement/knowledge material/courses&quot;, &quot;attending conferences&quot;, etc. But just writing proper documents that are to be used by people of varying technical literacy is a valuable skill. No-one is expected to do all things required for software development super-well, but this is probably one of those things that translates into any field of work, any language stack, any problem domain.</p>
<p><span class="since">(Addendum 2026-03-14:</span> This is one of the things that seem to be very important for Agentic coding...<span class="since">)</span></p>
<p>Then you'll see companies hiring for remote positions, but <code>they can't produce any written documents, or specifications</code>. In terms of hiring I also think that this is something that can be greatly improved by having a culture of written first. If your processes, your software, your systems, are documented, it's fairly more easy to:</p>
<ul>
  <li class="sub-li"><span class="since">Produce a specification</span> for interview takeaway problems (either new, or using something already implemented, in that case if you have tests then you can automatically measure the functionality of the returned solutions and then look into subjective aspects such as code organisation and others) - this is enabled because it's normal to specify things, and so it's easier to generate a new one because PMs, software engineers `(?!)`, and others have at least some experience doing it;</li>
  <li class="sub-li"><span class="since">Communicate effectively asynchronously</span> - if your company can't produce written documentation, can't communicate clearly through written form, how am I supposed to believe somehow you are able to foster a remote environment that has any semblance of working?</li>
  <li class="sub-li"><span class="since">Onboard new people</span> - yes, nothing replaces being able to talk directly to a person and have a question answered on the spot - the issue is that given the complexity of software systems, there is a lot of groundwork that needs to be done when coming up to speed - if the answers for 70% of it are written and discoverable, it's better than 0% and 100% of the questions needing some person to answer them, or having to figure them out by backtracking through actual code, instead of clearer high-level descriptions;</li>
  <li class="sub-li"><span class="since">Inter/intra team communication</span> - if nothing is written, again the overhead of sharing knowledge is extremely high - some people will also be reluctant to engage if the other person doesn't show that at least they tried understanding something first - written documents can help this as well, since someone can do their own research and be left only with questions related to details - or not have questions afterall - it also shows how the documentation might be improved or is somehow missing so effective documentation improvements can be fed into these loops;</li>
  <li class="sub-li">Lastly, and this is perhaps personal, I think it's also a proxy for team fit - not a fit into a particular team, but fit into the idea of being in a team - people who take care in explaining how things work in order to be grokkable by others seem to me more inclined to care less about politics and not of being in a position just to take a payment at the end of the month/sprint - basically because by making their work accessible to others they're removing the need to rely on their tacit knowledge.</li>
</ul>
<hr class="hr-separator-b">
<p>This is why to me it's a bit mind-boggling that it's not a core part of software development team processes. It's not only for developers, it's for <code>PMs</code> too and other members. It's not only about <code>facilitating knowledge sharing</code> and <code>reducing bus factor</code>, it's also about <code>improving skills</code> that are useful in a wide range of fields <code>beyond software development</code> (the ability to express ideas in the written form - because that scales). It's not only about empowering developers but about steering product development to a model where things are based more on their merits than on who has the most clout, political or personal, or who is the smartest-talking ape. It's also funny that people eagerly will copy tech-stacks and easy to do rituals (like stand-ups, daily calls, etc) from successful companies, but then the things that are far-reaching, such as emphasis on written documentation/preparation/spec'ing, are just ignored, probably because you can't just tick an item off a list and have to actually produce usable artefacts.</p>
<p>So the take-away I want to leave you with is; <code>if you want to improve the quality of software that you or your team is producing, you want to empower and make a more resilient team, and diminish the long-term cost of software - start by documenting, spec'ing, testing and making this part of the normal expected workflow</code>.</p>
<p>Most software <code>might start trivial</code>, or start as different services trivilly glued together, but <code>complexity grows exponentially as it develops</code> - not only because it has to take care of much more use cases as it expands, but because it usually has to rely on an increasing number of moving parts, from infrastructure, to packages, libraries, different languages, deployment targets, requirements and constraints and the costs of lacking &quot;written artefacts&quot; remain hidden. A developer that quits because everything is an ungrokkable mess doesn't show up as a direct cost of this. A developer having their productivity hampered in half doesn't show up as this. The need for a re-write because no one understands the system anymore doesn't show up as a cost of this. A new-hire having to spend valuable time from other more knowledgeable developers, that could easily be documented, doesn't show as related to this. Your PMs making wrong decisions doesn't either.</p>
<p>In the end, most of this is related to two things:</p>
<ul>
  <li class="sub-li">the lack of willingness to admit that the written part of software development is essential - which shouldn't be a suprise since what we do as developers is writing code, sometimes comments, and we all know that the difficult part is clarifying the logic of what something should do and not the syntax specifics of given languages;</li>
  <li class="sub-li">the build to be acquired mentality - it doesn't matter if it's a turd, as long as you can make it look nice on numbers - many endeavours in software seem to only have the goal of being sold - and when that is the case, effectively, these might be additional costs and just feature after feature in a checklist, even if the base is a steeming pile, make it look more palatable - the truth is, it can also sink these ones, there's a breaking point after which you might not be able to have functioning systems and produce new features, and no matter how you sell it, it will show.</li>
<hr class="hr-separator-b">
<p>(of course, as with everything, there needs to be a balance, the same way you don't need to test everything that is in your code base to have a good degree of confidence, you might only test the overall code &quot;paths&quot; in some end-to-end fashion, and then specific functionality isolatedly, some things are self documenting, but I would arguee that many, surprisingly, are not, for anyone else than the one writing them - and that has a time validity as well, just like yogurt, after which they too, no longer understand their <code>&quot;clear self-documenting code&quot;</code>)</p> ]]></description>
    </item>
    <item>
       <title>ImageEngine with Next.js</title>
       <link>https://micaelnussbaumer.com/posts/imageengine-w-nextjs</link>
       <pubDate>Thu, 10 Jun 2021 16:30:00 +07</pubDate>
       <guid>https://micaelnussbaumer.com/posts/imageengine-w-nextjs</guid>
       <description><![CDATA[ <h4><a href="#using-imageengine-in-a-reactjs-project" aria-hidden="true" class="anchor" id="using-imageengine-in-a-reactjs-project"></a>Using ImageEngine in a React.js project</h4>
<p>In this blog post we'll cover how to use ImageEngine in order to significantly improve your image assets, increasing your site responsiveness and improving your loading times - easy mode.</p>
<p><a href="http://mnussbaumer-image-engine-sample.s3-website-us-west-2.amazonaws.com">You can check the final website we'll be building (requires JS, no cookies)</a></p>
<p>There's also a <a href="https://github.com/mnussbaumer/ie-nextjs-sample">repository</a> containing all the code.</p>
<p>This post was originally published on <a href="https://dev.to/mnussbaumer/imageengine-with-nextjs-1dh7">dev.to</a></p>
<h4><a href="#why-use-imageengine-ie-to-optimize-your-images" aria-hidden="true" class="anchor" id="why-use-imageengine-ie-to-optimize-your-images"></a>Why use ImageEngine (IE) to optimize your images?</h4>
<p>While this post is particular to <code>Next.js</code> when exporting a static website - a case where <code>Next.js</code> inbuilt <code>Image Loader</code>, and its optimisations can't be used - <code>IE</code> only requires a query string on your image urls and can be used in any stack, even outside websites.</p>
<p><code>Next.js</code> also has the capability of specifying custom image loaders for their inbuilt <code>&lt;Image/&gt;</code> component, and we can use those to reach an external CDN from which to load our images with our own logic - we'll go through that in another blog post.</p>
<p>If using <code>Next.js</code> with a <code>Nodejs</code> server and their inbuilt image optimisations, both the image optimisations and the serving of the assets will be done from the server side, while using <code>IE</code> none of it has to pass through your server with exception of the first serving - that coupled with the full range of customisable properties and highly optimised algorithms <code>IE</code> offers, makes it worth considering.</p>
<p>The only exception is in case you're deploying directly in <code>vercel.com</code>, their whole infra-structure supports <code>Next.js</code> inbuilt <code>Image Optimizations</code> (with automatic edge caching and good performance overall) which is good enough for most cases. Although even then, <code>IE</code> can provide significant bandwidth and improved response times savings over it, specially if you're serving a non trivial amount of images.</p>
<p>I'm going to walk you through implementing the website and deploying it on <code>S3</code>, using <code>IE</code> to optimise the delivery of its image content.</p>
<h4><a href="#how-can-we-use-ie-to-improve-our-nextjs-app-loading-speed" aria-hidden="true" class="anchor" id="how-can-we-use-ie-to-improve-our-nextjs-app-loading-speed"></a>How can we use IE to improve our Nextjs app loading speed?</h4>
<p>First let's go through the website so that you can make sense of what's happening and what we'll be building.</p>
<p>The website is designed to show the difference in file sizes, and consequently in loading times, between images distributed in their original versions and images distributed through <code>ImageEngine</code>'s smart <code>CDN</code>. Notice that the images that comprise the repository are sourced from the same files, but by using <code>IE</code> we can do some neat things with them.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z2ejbeqyh5otbl9vmusa.jpg" alt="View of the final website" /></p>
<p>The thumbnails on the left are from images on the <code>IE CDN</code>, optimised through simple URL <code>directives</code>. This means that specifications such as <code>width</code>, <code>height</code>, <code>compression</code>, etc, are simply passed through query parameters on the URL the image tags use, without requiring any additional work.</p>
<p>The thumbnails on the right side are from the original resources.</p>
<p>If you click any thumbnail or file title from the sidebar, you'll see that for the <code>IE</code> side, the total size now increased to account for that, while the normal assets didn't - because they were already loaded.</p>
<p>Of note is that many times, when loading a website, there's no actual need of loading full sized images, so optimising thumbnails is immediately an advantage in the majority of cases - because it allows a much faster initial load it impacts directly <a href="https://imageengine.io/blog/improve-core-web-vitals-with-imageengine">Google’s Core Web Vitals</a> scoring.</p>
<p>In the same way the thumbnails were optimised through <code>directives</code>, we can also optimise those being displayed on the &quot;preview&quot; area. From the sidebar select, <code>Pick a type</code> -&gt; <code>jpg</code>, <code>Pick a fit type</code> -&gt; <code>cropbox</code> and enter <code>600</code> as the <code>width</code> and <code>400</code> as the <code>height directive</code>. There's others, like <code>compression</code>, <code>sharpness</code>, and so on that aren't on the sidebar, but available to use.</p>
<p>You should see some significant improvements on the size without any perceivable quality loss. At <code>600px X 400px</code>, it’s enough to cover retina when displaying images at <code>300px X 200px</code>, which is roughly the size of our previews.</p>
<p>Click around on the thumbnails to see the time images take to be displayed between changes. Even though the regular images are already downloaded and cached by the browser you can still see significant differences (<code>IE</code> images on first load, or when changing directives have to be fully processed and transferred, and usually still render faster than the unoptimized ones already downloaded and cached!).</p>
<p>Let's start actually coding this.</p>
<h4><a href="#setting-up-the-nextjs-project" aria-hidden="true" class="anchor" id="setting-up-the-nextjs-project"></a>Setting up the Next.js project</h4>
<p>To follow through you'll need to have <code>nodejs</code> and <code>npm</code> installed. The versions used for this tutorial are <code>npm 6.14.4</code> and <code>node v10.19.0</code>.</p>
<p>On the folder where you'll be creating your project run:</p>
<p><code>npx create-next-app</code></p>
<p>Now let's install the image engine package:</p>
<p><code>npm i @imageengine/react</code></p>
<p>We should be able to start our app by doing</p>
<p><code>npm run dev</code></p>
<p>And visiting</p>
<p><code>http://localhost:3000</code></p>
<p>should show us the default page. Let's remove the default templating <code>index.js</code> page has:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-javascript" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #dc8ed9;">import</span> <span style="color: #dbc074;">Head</span> <span style="color: #dc8ed9;">from</span> <span style="color: #81b29a;">&quot;next/head&quot;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3"><span style="color: #dc8ed9;">export</span> <span style="color: #9d79d6;">default</span> <span style="color: #9d79d6;">function</span> <span style="color: #86abdc;">Home</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="4">  <span style="color: #c94f6d;">return</span> <span style="color: #aeafb0;">(</span>
</div><div class="line" data-line="5">      <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">div</span> <span style="color: #86abdc;">className</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;main-container&quot;</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="6">        <span style="color: #7ad5d6;">&lt;</span><span style="color: #9d79d6;">Head</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="7">          <span style="color: #7ad5d6;">&lt;</span>title<span style="color: #7ad5d6;">&gt;</span><span style="color: #86abdc; font-weight: bold;">ImageEngine Optimized Assets</span><span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">title</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="8">        <span style="color: #7ad5d6;">&lt;/</span><span style="color: #9d79d6;">Head</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="9">      <span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">div</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="10">  <span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="11"><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">;</span>
</div></code></pre>
<p>And change <code>/pages/_app.js</code> to the following</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-javascript" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #dc8ed9;">import</span> <span style="color: #dbc074;">Head</span> <span style="color: #dc8ed9;">from</span> <span style="color: #81b29a;">&quot;next/head&quot;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="2"><span style="color: #dc8ed9;">import</span> <span style="color: #aeafb0;">&lbrace;</span> <span style="color: #dbc074;">ImageEngineProvider</span> <span style="color: #aeafb0;">&rbrace;</span> <span style="color: #dc8ed9;">from</span> <span style="color: #81b29a;">&quot;@imageengine/react&quot;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="3"><span style="color: #dc8ed9;">import</span> <span style="color: #81b29a;">&quot;../styles/globals.css&quot;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="4">
</div><div class="line" data-line="5"><span style="color: #9d79d6;">const</span> <span style="color: #dfdfe0;">delivery_address</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">process</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">env</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">DELIVERY_ADDRESS</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7"><span style="color: #9d79d6;">function</span> <span style="color: #86abdc;">LeanImages</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span> <span style="color: #7ad5d6;">Component</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">pageProps</span> <span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="8">    <span style="color: #c94f6d;">return</span> <span style="color: #aeafb0;">(</span>
</div><div class="line" data-line="9">	<span style="color: #7ad5d6;">&lt;</span><span style="color: #9d79d6;">ImageEngineProvider</span> <span style="color: #86abdc;">deliveryAddress</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">delivery_address</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="10">	  <span style="color: #7ad5d6;">&lt;</span><span style="color: #9d79d6;">Head</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="11">	    <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">link</span> <span style="color: #86abdc;">rel</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;icon&quot;</span> <span style="color: #86abdc;">type</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;image/png&quot;</span> href<span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;</span><span style="color: #f6b079; text-decoration: underline;">/favicon.png</span><span style="color: #81b29a;">&quot;</span><span style="color: #7ad5d6;">/&gt;</span>
</div><div class="line" data-line="12">	    <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">meta</span> <span style="color: #86abdc;">name</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;viewport&quot;</span> <span style="color: #86abdc;">content</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;initial-scale=1.0, width=device-width&quot;</span> <span style="color: #7ad5d6;">/&gt;</span>
</div><div class="line" data-line="13">	    <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">meta</span> <span style="color: #86abdc;">name</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;description&quot;</span> <span style="color: #86abdc;">content</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;Learn how to use ImageEngine in Nextjs to serve highly optimised image assets from your CDN to your users.&quot;</span> <span style="color: #7ad5d6;">/&gt;</span>
</div><div class="line" data-line="14">	    <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">meta</span> <span style="color: #86abdc;">property</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;og:title&quot;</span> <span style="color: #86abdc;">content</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;ImageEngine with NextJS&quot;</span> <span style="color: #7ad5d6;">/&gt;</span>
</div><div class="line" data-line="15">	    <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">meta</span> <span style="color: #86abdc;">property</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;og:description&quot;</span> <span style="color: #86abdc;">content</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;Learn how to use ImageEngine in Nextjs to serve highly optimised image assets from your CDN to your users.&quot;</span> <span style="color: #7ad5d6;">/&gt;</span>
</div><div class="line" data-line="16">	  <span style="color: #7ad5d6;">&lt;/</span><span style="color: #9d79d6;">Head</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="17">	  <span style="color: #7ad5d6;">&lt;</span><span style="color: #9d79d6;">Component</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">...</span><span style="color: #dfdfe0;">pageProps</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #7ad5d6;">/&gt;</span>
</div><div class="line" data-line="18">	<span style="color: #7ad5d6;">&lt;/</span><span style="color: #9d79d6;">ImageEngineProvider</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="19">    <span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="20"><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="21">
</div><div class="line" data-line="22"><span style="color: #dc8ed9;">export</span> <span style="color: #9d79d6;">default</span> <span style="color: #dbc074;">LeanImages</span><span style="color: #aeafb0;">;</span>
</div></code></pre>
<p>If you have your dev server running you should see an error. Let's stop the server and create a <code>next.config.js</code> on the root of our project and inside it:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-javascript" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #c94f6d;">module</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">exports</span> <span style="color: #aeafb0;">=</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="2">    <span style="color: #719cd6;">env</span><span style="color: #aeafb0;">:</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="3">	<span style="color: #719cd6;">DELIVERY_ADDRESS</span><span style="color: #aeafb0;">:</span> <span style="color: #dfdfe0;">process</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">env</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">DELIVERY_ADDRESS</span> <span style="color: #aeafb0;">||</span> <span style="color: #81b29a;">&quot;http://localhost:3000&quot;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="4">	<span style="color: #719cd6;">NON_OPTIMIZED_ADDRESS</span><span style="color: #aeafb0;">:</span> <span style="color: #dfdfe0;">process</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">env</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">NON_OPTIMIZED_ADDRESS</span> <span style="color: #aeafb0;">||</span> <span style="color: #81b29a;">&quot;&quot;</span>
</div><div class="line" data-line="5">    <span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="6"><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">;</span>
</div></code></pre>
<p>Let's remove the things we don't need, delete <code>pages/api</code> folder, <code>styles/Home.module.css</code> and <code>public/vercel.svg</code>::</p>
<p><code>rm -rf pages/api</code>
<code>rm styles/Home.module.css</code>
<code>rm public/vercel.svg</code></p>
<p>We should now have the following structure:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-javascript" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #dfdfe0;">pages</span> <span style="color: #aeafb0;">/</span>
</div><div class="line" data-line="2">  <span style="color: #dfdfe0;">_app</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">js</span>
</div><div class="line" data-line="3">  <span style="color: #dfdfe0;">index</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">js</span>
</div><div class="line" data-line="4"><span style="color: #dfdfe0;">styles</span> <span style="color: #aeafb0;">/</span>
</div><div class="line" data-line="5">  <span style="color: #dfdfe0;">global</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">css</span>
</div><div class="line" data-line="6"><span style="color: #dfdfe0;">public</span> <span style="color: #aeafb0;">/</span>
</div><div class="line" data-line="7">  <span style="color: #dfdfe0;">favicon</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">ico</span>
</div></code></pre>
<p>We're ready to start. Our website will be a single page, divided into <code>2</code> sections, one left sidebar and a main area, the latter further divided into <code>3</code> parts - the title and image information, the preview area, and the thumbnails section. From the sidebar we'll be able to choose certain parameters related to the image display, and we'll have a small list with actionable items.</p>
<p>When clicking one of those items it will display them in the main area, in two versions, one from our image engine distribution, and the other from our original assets.</p>
<p>Locally it will source both from the same place in our assets, but once online correctly from their origins.</p>
<p>We will also display the total transferred file size for each image and a cumulative for all images loaded, between <code>optimized</code> and <code>non-optimized</code>.</p>
<p>To share state between our components we’ll use <code>useReducer</code> so let's write its initial state, on our <code>pages/index.js</code>:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-javascript" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">const</span> <span style="color: #dfdfe0;">initial_settings_state</span> <span style="color: #aeafb0;">=</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="2">    <span style="color: #719cd6;">base_path</span><span style="color: #aeafb0;">:</span> <span style="color: #81b29a;">&quot;/images&quot;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="3">    <span style="color: #719cd6;">file_types</span><span style="color: #aeafb0;">:</span> <span style="color: #aeafb0;">[</span><span style="color: #81b29a;">&quot;jpg&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;jp2&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;webp&quot;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="4">    <span style="color: #719cd6;">file_type</span><span style="color: #aeafb0;">:</span> <span style="color: #f6b079;">null</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="5">    <span style="color: #719cd6;">fit_types</span><span style="color: #aeafb0;">:</span> <span style="color: #aeafb0;">[</span><span style="color: #81b29a;">&quot;stretch&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;box&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;letterbox&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;cropbox&quot;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="6">    <span style="color: #719cd6;">fit_type</span><span style="color: #aeafb0;">:</span> <span style="color: #f6b079;">null</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="7">    <span style="color: #719cd6;">width</span><span style="color: #aeafb0;">:</span> <span style="color: #f6b079;">null</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="8">    <span style="color: #719cd6;">height</span><span style="color: #aeafb0;">:</span> <span style="color: #f6b079;">null</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="9">    <span style="color: #719cd6;">images</span><span style="color: #aeafb0;">:</span> <span style="color: #aeafb0;">[</span>
</div><div class="line" data-line="10">    	<span style="color: #81b29a;">&quot;senja_norway.jpg&quot;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="11">    	<span style="color: #81b29a;">&quot;buddha_shakyamuni.jpg&quot;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="12">    	<span style="color: #81b29a;">&quot;vasnetsov_samolet.jpg&quot;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="13">    	<span style="color: #81b29a;">&quot;great_wave_off_kanagawa.jpg&quot;</span>
</div><div class="line" data-line="14">    <span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="15">    <span style="color: #719cd6;">copyright</span><span style="color: #aeafb0;">:</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="16">    	<span style="color: #81b29a;">&quot;great_wave_off_kanagawa.jpg&quot;</span><span style="color: #aeafb0;">:</span> <span style="color: #aeafb0;">[</span><span style="color: #81b29a;">&quot;Great Wave off Kanagawa&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;By After Katsushika Hokusai - Restored version, Public Domain&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #81b29a;">&quot;https://commons.wikimedia.org/w/index.php?curid=5576388&quot;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="17">    	<span style="color: #81b29a;">&quot;buddha_shakyamuni.jpg&quot;</span><span style="color: #aeafb0;">:</span> <span style="color: #aeafb0;">[</span><span style="color: #81b29a;">&quot;Buddha Shakyamuni&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;By Unknown author - Public Domain&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #81b29a;">&quot;https://www.metmuseum.org/collection/the-collection-online/search/75274&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;https://commons.wikimedia.org/w/index.php?curid=39112914&quot;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="18">    	<span style="color: #81b29a;">&quot;vasnetsov_samolet.jpg&quot;</span><span style="color: #aeafb0;">:</span> <span style="color: #aeafb0;">[</span><span style="color: #81b29a;">&quot;The Flying Carpet&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;By Viktor Mikhailovich Vasnetsov - belygorod.ru, Public Domain&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #81b29a;">&quot;https://commons.wikimedia.org/w/index.php?curid=1374733&quot;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="19">    	<span style="color: #81b29a;">&quot;senja_norway.jpg&quot;</span><span style="color: #aeafb0;">:</span> <span style="color: #aeafb0;">[</span><span style="color: #81b29a;">&quot;Island of Senja, Troms, Norway (August, 2014)&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;By Ximonic (Simo Räsänen) - Own work, CC BY-SA 4.0&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #81b29a;">&quot;https://commons.wikimedia.org/w/index.php?curid=34693021&quot;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="20">	
</div><div class="line" data-line="21">    <span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="22">    <span style="color: #719cd6;">show_copyright</span><span style="color: #aeafb0;">:</span> <span style="color: #f4a261;">false</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="23">    <span style="color: #719cd6;">loaded_images_ie</span><span style="color: #aeafb0;">:</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="24">    <span style="color: #719cd6;">loaded_images_regular</span><span style="color: #aeafb0;">:</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="25">    <span style="color: #719cd6;">selected_image</span><span style="color: #aeafb0;">:</span> <span style="color: #f6b079;">null</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="26">    <span style="color: #719cd6;">selected_image_url</span><span style="color: #aeafb0;">:</span> <span style="color: #f6b079;">null</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="27">    <span style="color: #719cd6;">force_load</span><span style="color: #aeafb0;">:</span> <span style="color: #f4a261;">false</span>
</div><div class="line" data-line="28"><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">;</span>
</div></code></pre>
<p>Our reducer function will be:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-javascript" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">function</span> <span style="color: #86abdc;">settings_reducer</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">state</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">action</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="2">    <span style="color: #baa1e2;">switch</span> <span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">action</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">type</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="3">    <span style="color: #baa1e2;">case</span> <span style="color: #81b29a;">&quot;file_type&quot;</span><span style="color: #aeafb0;">:</span>
</div><div class="line" data-line="4">    <span style="color: #baa1e2;">case</span> <span style="color: #81b29a;">&quot;fit_type&quot;</span><span style="color: #aeafb0;">:</span>
</div><div class="line" data-line="5">    <span style="color: #baa1e2;">case</span> <span style="color: #81b29a;">&quot;width&quot;</span><span style="color: #aeafb0;">:</span>
</div><div class="line" data-line="6">    <span style="color: #baa1e2;">case</span> <span style="color: #81b29a;">&quot;height&quot;</span><span style="color: #aeafb0;">:</span>
</div><div class="line" data-line="7">    <span style="color: #baa1e2;">case</span> <span style="color: #81b29a;">&quot;force_load&quot;</span><span style="color: #aeafb0;">:</span>
</div><div class="line" data-line="8">    <span style="color: #baa1e2;">case</span> <span style="color: #81b29a;">&quot;show_copyright&quot;</span><span style="color: #aeafb0;">:</span>
</div><div class="line" data-line="9">    	<span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">action</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">type</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">action</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">value</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="10">    	<span style="color: #c94f6d;">return</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">...</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="11">	
</div><div class="line" data-line="12">    <span style="color: #baa1e2;">case</span> <span style="color: #81b29a;">&quot;selected_image&quot;</span><span style="color: #aeafb0;">:</span>
</div><div class="line" data-line="13">    	<span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">selected_image</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">action</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">value</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="14">    	<span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">selected_image_url</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">action</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">value</span> <span style="color: #baa1e2;">?</span> <span style="color: #81b29a;">`$&lbrace;</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">base_path</span><span style="color: #7ad5d6;">&rbrace;</span><span style="color: #81b29a;">/$&lbrace;</span><span style="color: #dfdfe0;">action</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">value</span><span style="color: #7ad5d6;">&rbrace;</span><span style="color: #81b29a;">`</span> <span style="color: #baa1e2;">:</span> <span style="color: #f6b079;">null</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="15">    	<span style="color: #c94f6d;">return</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">...</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="16">
</div><div class="line" data-line="17">    <span style="color: #baa1e2;">case</span> <span style="color: #81b29a;">&quot;add_image_size&quot;</span><span style="color: #aeafb0;">:</span>
</div><div class="line" data-line="18">    	<span style="color: #9d79d6;">let</span> <span style="color: #dfdfe0;">state_key</span> <span style="color: #aeafb0;">=</span> <span style="color: #86abdc;">build_type_key</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">action</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">image_type</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="19">	
</div><div class="line" data-line="20">    	<span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">state_key</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">action</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">image</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">action</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">size</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="21">    	<span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">state_key</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">=</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">...</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">state_key</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="22">
</div><div class="line" data-line="23">    	<span style="color: #c94f6d;">return</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">...</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="24">    <span style="color: #baa1e2;">default</span><span style="color: #aeafb0;">:</span>
</div><div class="line" data-line="25">        <span style="color: #9d79d6;">throw</span> <span style="color: #aeafb0;">new</span> <span style="color: #63cdcf;">Error</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="26">  <span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="27"><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">;</span>
</div></code></pre>
<p>You might see an error because <code>build_type_key(action.image_type)</code> isn’t defined yet, we’ll add it in a while.</p>
<h4><a href="#sidebar-component" aria-hidden="true" class="anchor" id="sidebar-component"></a>Sidebar component</h4>
<p>Now our <code>sidebar</code> component. Create a folder <code>components</code> on the root folder and inside it a <code>sidebar.js</code> file:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-javascript" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #dc8ed9;">import</span> <span style="color: #dbc074;">React</span> <span style="color: #dc8ed9;">from</span> <span style="color: #81b29a;">&quot;react&quot;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3"><span style="color: #dc8ed9;">export</span> <span style="color: #9d79d6;">default</span> <span style="color: #9d79d6;">function</span> <span style="color: #86abdc;">Sidebar</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span> <span style="color: #7ad5d6;">state</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">dispatch</span> <span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="4">    <span style="color: #c94f6d;">return</span> <span style="color: #aeafb0;">(</span>
</div><div class="line" data-line="5">	<span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">div</span> <span style="color: #86abdc;">className</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;sidebar-wrapper&quot;</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="6">	  <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">div</span> <span style="color: #86abdc;">className</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;sidebar&quot;</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="7">	    <span style="color: #7ad5d6;">&lt;</span>h2<span style="color: #7ad5d6;">&gt;</span><span style="color: #86abdc; font-weight: bold;">Directives Optimizations</span><span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">h2</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="8">	    <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">select</span> <span style="color: #86abdc;">id</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;file_type&quot;</span> <span style="color: #86abdc;">name</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;file_type&quot;</span> <span style="color: #86abdc;">value</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">file_type</span> <span style="color: #aeafb0;">||</span> <span style="color: #81b29a;">&quot;&quot;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #86abdc;">onChange</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">event</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #86abdc;">dispatch</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #719cd6;">type</span><span style="color: #aeafb0;">:</span> <span style="color: #81b29a;">&quot;file_type&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #719cd6;">value</span><span style="color: #aeafb0;">:</span> <span style="color: #dfdfe0;">event</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">target</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">value</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="9">	      <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">option</span> <span style="color: #86abdc;">value</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;&quot;</span> <span style="color: #7ad5d6;">&gt;</span>Pick a type<span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">option</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="10">	      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">file_types</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">map</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">index</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="11">                <span style="color: #c94f6d;">return</span>  <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">option</span> <span style="color: #86abdc;">value</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #86abdc;">key</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #81b29a;">`file_type-</span><span style="color: #7ad5d6;">$&lbrace;</span><span style="color: #dfdfe0;">index</span><span style="color: #7ad5d6;">&rbrace;</span><span style="color: #81b29a;">`</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #7ad5d6;">&gt;</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">option</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="12">	      <span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="13">	    <span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">select</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="14">	    <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">br</span><span style="color: #7ad5d6;">/&gt;</span>
</div><div class="line" data-line="15">	    <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">br</span><span style="color: #7ad5d6;">/&gt;</span>
</div><div class="line" data-line="16">	    <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">select</span> <span style="color: #86abdc;">id</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;fit_type&quot;</span> <span style="color: #86abdc;">name</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;fit_type&quot;</span> <span style="color: #86abdc;">value</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">fit_type</span> <span style="color: #aeafb0;">||</span> <span style="color: #81b29a;">&quot;&quot;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #86abdc;">onChange</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">event</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #86abdc;">dispatch</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #719cd6;">type</span><span style="color: #aeafb0;">:</span> <span style="color: #81b29a;">&quot;fit_type&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #719cd6;">value</span><span style="color: #aeafb0;">:</span> <span style="color: #dfdfe0;">event</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">target</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">value</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="17">	      <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">option</span> <span style="color: #86abdc;">value</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;&quot;</span><span style="color: #7ad5d6;">&gt;</span>Pick a fit type<span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">option</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="18">	      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">fit_types</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">map</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">index</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="19">                <span style="color: #c94f6d;">return</span>  <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">option</span> <span style="color: #86abdc;">value</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #86abdc;">key</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #81b29a;">`file_type-</span><span style="color: #7ad5d6;">$&lbrace;</span><span style="color: #dfdfe0;">index</span><span style="color: #7ad5d6;">&rbrace;</span><span style="color: #81b29a;">`</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #7ad5d6;">&gt;</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">option</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="20">	      <span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="21">	    <span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">select</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="22">	    <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">br</span><span style="color: #7ad5d6;">/&gt;</span>
</div><div class="line" data-line="23">	    <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">br</span><span style="color: #7ad5d6;">/&gt;</span>
</div><div class="line" data-line="24">	    <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">input</span> <span style="color: #86abdc;">type</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;text&quot;</span> <span style="color: #86abdc;">name</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;width&quot;</span> <span style="color: #86abdc;">id</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;width&quot;</span> <span style="color: #86abdc;">placeholder</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;Width directive in px, e.g: 25&quot;</span> <span style="color: #86abdc;">value</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">width</span> <span style="color: #aeafb0;">||</span> <span style="color: #81b29a;">&quot;&quot;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #86abdc;">onChange</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">event</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #86abdc;">dispatch</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #719cd6;">type</span><span style="color: #aeafb0;">:</span> <span style="color: #81b29a;">&quot;width&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #719cd6;">value</span><span style="color: #aeafb0;">:</span> <span style="color: #dfdfe0;">event</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">target</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">value</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #7ad5d6;">/&gt;</span>
</div><div class="line" data-line="25">	    <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">br</span><span style="color: #7ad5d6;">/&gt;</span>
</div><div class="line" data-line="26">	    <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">br</span><span style="color: #7ad5d6;">/&gt;</span>
</div><div class="line" data-line="27">	    <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">input</span> <span style="color: #86abdc;">type</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;text&quot;</span> <span style="color: #86abdc;">name</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;height&quot;</span> <span style="color: #86abdc;">id</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;height&quot;</span> <span style="color: #86abdc;">placeholder</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;Height directive in px, e.g: 50&quot;</span> <span style="color: #86abdc;">value</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">height</span> <span style="color: #aeafb0;">||</span> <span style="color: #81b29a;">&quot;&quot;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #86abdc;">onChange</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">event</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #86abdc;">dispatch</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #719cd6;">type</span><span style="color: #aeafb0;">:</span> <span style="color: #81b29a;">&quot;height&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #719cd6;">value</span><span style="color: #aeafb0;">:</span> <span style="color: #dfdfe0;">event</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">target</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">value</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #7ad5d6;">/&gt;</span>
</div><div class="line" data-line="28">            <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">ul</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="29">              <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">images</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">map</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">image</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">index</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="30">                <span style="color: #c94f6d;">return</span> <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">li</span> <span style="color: #86abdc;">key</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #81b29a;">`image-</span><span style="color: #7ad5d6;">$&lbrace;</span><span style="color: #dfdfe0;">index</span><span style="color: #7ad5d6;">&rbrace;</span><span style="color: #81b29a;">`</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #86abdc;">className</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #81b29a;">`</span><span style="color: #7ad5d6;">$&lbrace;</span><span style="color: #dfdfe0;">image</span> <span style="color: #aeafb0;">===</span> <span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">selected_image</span> <span style="color: #baa1e2;">?</span> <span style="color: #81b29a;">&quot;selected&quot;</span> <span style="color: #baa1e2;">:</span> <span style="color: #81b29a;">&quot;&quot;</span><span style="color: #7ad5d6;">&rbrace;</span><span style="color: #81b29a;">`</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #86abdc;">onClick</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #86abdc;">dispatch</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #719cd6;">type</span><span style="color: #aeafb0;">:</span> <span style="color: #81b29a;">&quot;selected_image&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #719cd6;">value</span><span style="color: #aeafb0;">:</span> <span style="color: #dfdfe0;">image</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #7ad5d6;">&gt;</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">image</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">li</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="31">               <span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="32">            <span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">ul</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="33">	  <span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">div</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="34">	<span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">div</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="35">    <span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="36"><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">;</span>
</div></code></pre>
<p>We have<code>select</code>s, <code>input</code>s and a list of elements. We set handlers to trigger on change for the inputs and dispatch the changes to our reducer, and click handlers on the list elements to dispatch the selection of an image.</p>
<p>Regarding the styling, to save some space I’ll link directly to the <a href="https://github.com/mnussbaumer/ie-nextjs-sample/blob/main/styles/globals.css">final css file</a>. Either copy the whole file or otherwise add it piece by piece as I’ll mention the initial line (<code>IL</code>) and last line (<code>LL</code>) for each component. In this case <code>IL0 - LL128</code>.</p>
<p>The central part will be made of two sections, the top part - info and images previews - and the bottom thumbnail section.
Create three files on the <code>components</code> folder, <code>copyright.js</code>, <code>thumbnails.js</code> and <code>image_preview.js</code>.</p>
<h4><a href="#copyright-component" aria-hidden="true" class="anchor" id="copyright-component"></a>Copyright component</h4>
<p>On <code>copyright.js</code>:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-javascript" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #dc8ed9;">export</span> <span style="color: #9d79d6;">default</span> <span style="color: #9d79d6;">function</span> <span style="color: #86abdc;">Copyright</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span> <span style="color: #7ad5d6;">state</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">dispatch</span> <span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="2">    <span style="color: #baa1e2;">if</span> <span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">!</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">selected_image</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="3">	<span style="color: #c94f6d;">return</span> <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">div</span> <span style="color: #86abdc;">className</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;main-area-image-info&quot;</span><span style="color: #7ad5d6;">&gt;</span><span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">div</span><span style="color: #7ad5d6;">&gt;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="4">    <span style="color: #aeafb0;">&rbrace;</span> <span style="color: #baa1e2;">else</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="5">    	<span style="color: #9d79d6;">let</span> <span style="color: #dfdfe0;">copyright</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">copyright</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">selected_image</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="6">    	    <span style="color: #dfdfe0;">title</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">copyright</span><span style="color: #aeafb0;">[</span><span style="color: #f4a261;">0</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="7">    	    <span style="color: #dfdfe0;">description</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">copyright</span><span style="color: #aeafb0;">[</span><span style="color: #f4a261;">1</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="8">    	    <span style="color: #dfdfe0;">links</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">copyright</span><span style="color: #aeafb0;">[</span><span style="color: #f4a261;">2</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="9">
</div><div class="line" data-line="10">    	<span style="color: #c94f6d;">return</span> <span style="color: #aeafb0;">(</span>
</div><div class="line" data-line="11">    	    <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">div</span> <span style="color: #86abdc;">className</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;main-area-image-info&quot;</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="12">    	      <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">h4</span><span style="color: #7ad5d6;">&gt;</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">title</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">button</span> <span style="color: #86abdc;">className</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;collapse-btn&quot;</span> <span style="color: #86abdc;">type</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;button&quot;</span> <span style="color: #86abdc;">onClick</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #86abdc;">dispatch</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #719cd6;">type</span><span style="color: #aeafb0;">:</span> <span style="color: #81b29a;">&quot;show_copyright&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #719cd6;">value</span><span style="color: #aeafb0;">:</span> <span style="color: #aeafb0;">!</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">show_copyright</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #7ad5d6;">&gt;</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">show_copyright</span> <span style="color: #baa1e2;">?</span> <span style="color: #81b29a;">&quot;-&quot;</span> <span style="color: #baa1e2;">:</span> <span style="color: #81b29a;">&quot;+&quot;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">button</span><span style="color: #7ad5d6;">&gt;</span><span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">h4</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="13">    	      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">show_copyright</span> <span style="color: #baa1e2;">?</span> <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">div</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="14">	             	    <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">p</span><span style="color: #7ad5d6;">&gt;</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">description</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">p</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="15">     			<span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">links</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">map</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">link</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">index</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">a</span> <span style="color: #86abdc;">href</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">link</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #86abdc;">target</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;_blank&quot;</span> <span style="color: #86abdc;">key</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #81b29a;">`link-</span><span style="color: #7ad5d6;">$&lbrace;</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">selected_image</span><span style="color: #7ad5d6;">&rbrace;</span><span style="color: #81b29a;">-</span><span style="color: #7ad5d6;">$&lbrace;</span><span style="color: #dfdfe0;">index</span><span style="color: #7ad5d6;">&rbrace;</span><span style="color: #81b29a;">`</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #7ad5d6;">&gt;</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">link</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">br</span><span style="color: #7ad5d6;">/&gt;</span><span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">a</span><span style="color: #7ad5d6;">&gt;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="16">    	       <span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">div</span><span style="color: #7ad5d6;">&gt;</span> <span style="color: #baa1e2;">:</span>
</div><div class="line" data-line="17">    	       <span style="color: #f6b079;">null</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="18">    	    <span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">div</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="19">    	<span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="20">    <span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="21"><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">;</span>
</div></code></pre>
<p><code>styles/globals.css</code> add from <code>IL131 - LL166</code>.</p>
<h4><a href="#thumbnails-component" aria-hidden="true" class="anchor" id="thumbnails-component"></a>Thumbnails component</h4>
<p><code>thumbnails.js</code></p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-javascript" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #dc8ed9;">import</span> <span style="color: #aeafb0;">&lbrace;</span> <span style="color: #dbc074;">Image</span> <span style="color: #aeafb0;">&rbrace;</span> <span style="color: #dc8ed9;">from</span> <span style="color: #81b29a;">&quot;@imageengine/react&quot;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="2"><span style="color: #dc8ed9;">import</span> <span style="color: #aeafb0;">&lbrace;</span> <span style="color: #dfdfe0;">get_size</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">handle_image</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">NON_OPTIMIZED_ADDRESS</span> <span style="color: #aeafb0;">&rbrace;</span> <span style="color: #dc8ed9;">from</span> <span style="color: #81b29a;">&quot;../js/utilities&quot;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4"><span style="color: #dc8ed9;">export</span> <span style="color: #9d79d6;">default</span> <span style="color: #9d79d6;">function</span> <span style="color: #86abdc;">Thumbnails</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span> <span style="color: #7ad5d6;">state</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">dispatch</span> <span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="5">    
</div><div class="line" data-line="6">    <span style="color: #c94f6d;">return</span> <span style="color: #aeafb0;">(</span>
</div><div class="line" data-line="7">	<span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">div</span> <span style="color: #86abdc;">className</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;main-area-thumbnails&quot;</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="8">	  <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">div</span> <span style="color: #86abdc;">className</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;thumbnails-container optimized&quot;</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="9">	    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">force_load</span> <span style="color: #aeafb0;">&amp;&amp;</span> <span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">images</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">map</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">image</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">index</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="10">                 <span style="color: #9d79d6;">let</span> <span style="color: #dfdfe0;">image_path</span> <span style="color: #aeafb0;">=</span> <span style="color: #81b29a;">`</span><span style="color: #7ad5d6;">$&lbrace;</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">base_path</span><span style="color: #7ad5d6;">&rbrace;</span><span style="color: #81b29a;">/</span><span style="color: #7ad5d6;">$&lbrace;</span><span style="color: #dfdfe0;">image</span><span style="color: #7ad5d6;">&rbrace;</span><span style="color: #81b29a;">`</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="11">                     <span style="color: #dfdfe0;">thumb_id</span> <span style="color: #aeafb0;">=</span> <span style="color: #81b29a;">`thumb_</span><span style="color: #7ad5d6;">$&lbrace;</span><span style="color: #dfdfe0;">image_path</span><span style="color: #7ad5d6;">&rbrace;</span><span style="color: #81b29a;">`</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="12">                 <span style="color: #c94f6d;">return</span> <span style="color: #aeafb0;">(</span>
</div><div class="line" data-line="13">                    <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">div</span> <span style="color: #86abdc;">className</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;thumbnail-image&quot;</span> <span style="color: #86abdc;">key</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #81b29a;">`thumbnail-optimized-</span><span style="color: #7ad5d6;">$&lbrace;</span><span style="color: #dfdfe0;">index</span><span style="color: #7ad5d6;">&rbrace;</span><span style="color: #81b29a;">`</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #86abdc;">onClick</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #86abdc;">dispatch</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #719cd6;">type</span><span style="color: #aeafb0;">:</span> <span style="color: #81b29a;">&quot;selected_image&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #719cd6;">value</span><span style="color: #aeafb0;">:</span> <span style="color: #dfdfe0;">image</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="14">                      <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">div</span> <span style="color: #86abdc;">className</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;thumbnail-size&quot;</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="15">                        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">get_size</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;ie&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">thumb_id</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="16">                      <span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">div</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="17">                      <span style="color: #7ad5d6;">&lt;</span><span style="color: #9d79d6;">Image</span>
</div><div class="line" data-line="18">                        <span style="color: #86abdc;">src</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">image_path</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="19">                        <span style="color: #86abdc;">directives</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="20">                          <span style="color: #719cd6;">outputFormat</span><span style="color: #aeafb0;">:</span> <span style="color: #81b29a;">&quot;jpg&quot;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="21">                          <span style="color: #719cd6;">height</span><span style="color: #aeafb0;">:</span> <span style="color: #f4a261;">90</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="22">                          <span style="color: #719cd6;">width</span><span style="color: #aeafb0;">:</span> <span style="color: #f4a261;">90</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="23">                          <span style="color: #719cd6;">fitMethod</span><span style="color: #aeafb0;">:</span> <span style="color: #81b29a;">&quot;cropbox&quot;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="24">                          <span style="color: #719cd6;">compression</span><span style="color: #aeafb0;">:</span> <span style="color: #f4a261;">80</span>
</div><div class="line" data-line="25">                        <span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="26">                        <span style="color: #86abdc;">onLoad</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">event</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #86abdc;">handle_image</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;ie&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">event</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">target</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">thumb_id</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">dispatch</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="27">                      <span style="color: #7ad5d6;">/&gt;</span>
</div><div class="line" data-line="28">		    <span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">div</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="29">		<span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="30">	    <span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="31">	  <span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">div</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="32">	  <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">div</span> <span style="color: #86abdc;">className</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;thumbnails-container regular&quot;</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="33">            <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">force_load</span> <span style="color: #aeafb0;">&amp;&amp;</span> <span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">images</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">map</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">image</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">index</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="34">              <span style="color: #9d79d6;">let</span> <span style="color: #dfdfe0;">image_path</span> <span style="color: #aeafb0;">=</span> <span style="color: #81b29a;">`</span><span style="color: #7ad5d6;">$&lbrace;</span><span style="color: #f6b079;">NON_OPTIMIZED_ADDRESS</span><span style="color: #7ad5d6;">&rbrace;</span><span style="color: #7ad5d6;">$&lbrace;</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">base_path</span><span style="color: #7ad5d6;">&rbrace;</span><span style="color: #81b29a;">/</span><span style="color: #7ad5d6;">$&lbrace;</span><span style="color: #dfdfe0;">image</span><span style="color: #7ad5d6;">&rbrace;</span><span style="color: #81b29a;">`</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="35">              <span style="color: #c94f6d;">return</span> <span style="color: #aeafb0;">(</span>
</div><div class="line" data-line="36">                  <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">div</span> <span style="color: #86abdc;">className</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;thumbnail-image&quot;</span> <span style="color: #86abdc;">key</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #81b29a;">`thumbnail-regular-</span><span style="color: #7ad5d6;">$&lbrace;</span><span style="color: #dfdfe0;">index</span><span style="color: #7ad5d6;">&rbrace;</span><span style="color: #81b29a;">`</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #86abdc;">onClick</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #86abdc;">dispatch</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #719cd6;">type</span><span style="color: #aeafb0;">:</span> <span style="color: #81b29a;">&quot;selected_image&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #719cd6;">value</span><span style="color: #aeafb0;">:</span> <span style="color: #dfdfe0;">image</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="37">                     <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">div</span> <span style="color: #86abdc;">className</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;thumbnail-size&quot;</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="38">                        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">get_size</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;regular&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">image_path</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="39">                     <span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">div</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="40">                     <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">img</span> <span style="color: #86abdc;">src</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">image_path</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #86abdc;">onLoad</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">event</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #86abdc;">handle_image</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;regular&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">event</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">target</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">image_path</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">dispatch</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #7ad5d6;">/&gt;</span>
</div><div class="line" data-line="41">                  <span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">div</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="42">                <span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="43">	    <span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="44">	  <span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">div</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="45">	<span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">div</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="46">    <span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="47"><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">;</span>
</div></code></pre>
<p>Here we'll use the <code>Image</code> component provided by the <code>@imageengine/react</code> package, and import a bunch of helper functions not yet defined.
We have two containers, on each of these containers we map the <code>images</code> we have to image elements - on the <code>optimized</code> one we build the full path, and create a unique id for this thumbnail. We display the size of that image with <code>get_size</code> and use IE’s <code>Image</code> component to build a custom image source.</p>
<p>On the <code>regular</code> one we do the same mapping but use a bare <code>&lt;img&gt;</code> tag. In these we don't create a <code>thumb_id</code> because the images will be these, but  on the <code>optimized</code> ones in order to account correctly for the total size of files being loaded we need to differentiate between the <code>thumbnails</code> retrieved from <code>IE</code> and the previews.
We’re using <code>state.force_load</code> to control the rendering, this is a walk-around for a glitch that happens on first load where sometimes the thumbnails won’t trigger the loaded handler.</p>
<h4><a href="#helper-functions" aria-hidden="true" class="anchor" id="helper-functions"></a>Helper functions</h4>
<p>For the helper functions, create a directory named <code>js</code>, and inside it a file named <code>utilities.js</code>:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-javascript" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #dc8ed9;">export</span> <span style="color: #9d79d6;">const</span> <span style="color: #f6b079;">NON_OPTIMIZED_ADDRESS</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">process</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">env</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">NON_OPTIMIZED_ADDRESS</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3"><span style="color: #dc8ed9;">export</span> <span style="color: #9d79d6;">async</span> <span style="color: #9d79d6;">function</span> <span style="color: #86abdc;">handle_image</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">image_type</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">img</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">selected_image_url</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">dispatch</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="4">
</div><div class="line" data-line="5">    <span style="color: #9d79d6;">let</span> <span style="color: #dfdfe0;">head</span> <span style="color: #aeafb0;">=</span> <span style="color: #9d79d6;">await</span> <span style="color: #86abdc;">fetch</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">img</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">src</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #719cd6;">method</span><span style="color: #aeafb0;">:</span> <span style="color: #81b29a;">&quot;head&quot;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="6">        <span style="color: #dfdfe0;">size</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">head</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">headers</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">get</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;content-length&quot;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="7">
</div><div class="line" data-line="8">    <span style="color: #baa1e2;">if</span> <span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">size</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="9">      <span style="color: #86abdc;">dispatch</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #719cd6;">type</span><span style="color: #aeafb0;">:</span> <span style="color: #81b29a;">&quot;add_image_size&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #719cd6;">image_type</span><span style="color: #aeafb0;">:</span> <span style="color: #dfdfe0;">image_type</span><span style="color: #aeafb0;">,</span> <span style="color: #719cd6;">image</span><span style="color: #aeafb0;">:</span> <span style="color: #dfdfe0;">selected_image_url</span><span style="color: #aeafb0;">,</span> <span style="color: #719cd6;">size</span><span style="color: #aeafb0;">:</span> <span style="color: #c94f6d;">parseInt</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">size</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="10">    <span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="11"><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="12">
</div><div class="line" data-line="13"><span style="color: #dc8ed9;">export</span> <span style="color: #9d79d6;">function</span> <span style="color: #86abdc;">get_size</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">state</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">url</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="14">    <span style="color: #9d79d6;">let</span> <span style="color: #dfdfe0;">size</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">build_type_key</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">url</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="15">    <span style="color: #c94f6d;">return</span>  <span style="color: #dfdfe0;">size</span> <span style="color: #aeafb0;">||</span> <span style="color: #dfdfe0;">size</span> <span style="color: #aeafb0;">===</span> <span style="color: #f4a261;">0</span> <span style="color: #baa1e2;">?</span> <span style="color: #86abdc;">display_size</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">size</span><span style="color: #aeafb0;">)</span> <span style="color: #baa1e2;">:</span> <span style="color: #81b29a;">&quot;No info&quot;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="16"><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="17">
</div><div class="line" data-line="18"><span style="color: #dc8ed9;">export</span> <span style="color: #9d79d6;">function</span> <span style="color: #86abdc;">calc_total_sizes</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">state</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">type</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="19">    <span style="color: #9d79d6;">let</span> <span style="color: #dfdfe0;">total_size</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Object</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">values</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">build_type_key</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">size</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #dfdfe0;">acc</span> <span style="color: #aeafb0;">+</span> <span style="color: #dfdfe0;">size</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">0</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="20">    <span style="color: #c94f6d;">return</span> <span style="color: #86abdc;">display_size</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">total_size</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="21"><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="22">
</div><div class="line" data-line="23"><span style="color: #dc8ed9;">export</span> <span style="color: #9d79d6;">function</span> <span style="color: #86abdc;">build_type_key</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">type</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="24">    <span style="color: #c94f6d;">return</span> <span style="color: #81b29a;">`loaded_images_$&lbrace;</span><span style="color: #dfdfe0;">type</span><span style="color: #7ad5d6;">&rbrace;</span><span style="color: #81b29a;">`</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="25"><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="26">
</div><div class="line" data-line="27"><span style="color: #9d79d6;">function</span> <span style="color: #86abdc;">display_size</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">size</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="28">    <span style="color: #baa1e2;">if</span> <span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">size</span> <span style="color: #aeafb0;">&gt;</span> <span style="color: #f4a261;">1048576</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="29">      <span style="color: #c94f6d;">return</span> <span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">Math</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">round</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">size</span> <span style="color: #aeafb0;">/</span> <span style="color: #f4a261;">1048576</span> <span style="color: #aeafb0;">+</span> <span style="color: #7ad5d6;">Number</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">EPSILON</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">*</span> <span style="color: #f4a261;">100</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">/</span> <span style="color: #f4a261;">100</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">+</span> <span style="color: #81b29a;">&quot;MB&quot;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="30">    <span style="color: #aeafb0;">&rbrace;</span> <span style="color: #baa1e2;">else</span> <span style="color: #baa1e2;">if</span> <span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">size</span> <span style="color: #aeafb0;">&gt;</span> <span style="color: #f4a261;">1024</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="31">      <span style="color: #c94f6d;">return</span> <span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">Math</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">round</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">size</span> <span style="color: #aeafb0;">/</span> <span style="color: #f4a261;">1024</span> <span style="color: #aeafb0;">+</span> <span style="color: #7ad5d6;">Number</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">EPSILON</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">*</span> <span style="color: #f4a261;">100</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">/</span> <span style="color: #f4a261;">100</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">+</span> <span style="color: #81b29a;">&quot;Kb&quot;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="32">    <span style="color: #aeafb0;">&rbrace;</span> <span style="color: #baa1e2;">else</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="33">      <span style="color: #c94f6d;">return</span> <span style="color: #dfdfe0;">size</span> <span style="color: #aeafb0;">+</span> <span style="color: #81b29a;">&quot;b&quot;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="34">    <span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="35"><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">;</span>
</div></code></pre>
<p>Let's go through each element here:</p>
<ul>
<li><code>NON_OPTIMIZED_ADDRESS</code> just proxies the value we will set as an <code>ENV</code> variable, to be picked from our <code>next.config.js</code> we created earlier.</li>
<li><code>handle_image</code> is the function we're using when an image finishes loading. It takes 4 arguments:
<ul>
<li><code>image_type</code> - if it's <code>ie</code> or <code>regular</code> so we can distinguish between which kind of image was loaded</li>
<li><code>img</code> - which is the <code>html img</code> element itself</li>
<li><code>selected_image_url</code> - which is the <code>key</code> under which we to correlate with this image</li>
<li><code>dispatch</code> - which is our reducer's dispatch function.</li>
</ul>
</li>
</ul>
<p>Now, there isn't a straightforward way in JS to get an image size that works every time for local, cross-origin, and cached files, so our solution is to issue an <code>head</code> request for the same resource. We use the actual <code>img</code> element to retrieve the exact <code>src</code> attribute. The response to this request includes the size of the resource, under the <code>content-length</code> header, but without actually transferring its content.</p>
<ul>
<li><code>get_size</code> is an helper that retrieves the correct size, for a particular url of a given type from our <code>state</code>.</li>
<li><code>calc_total_sizes</code> sums up the sizes of all resources we have retrieved for a given type.</li>
<li><code>build_type_key</code> is a simple helper to return the correct state key for a given type.</li>
<li><code>display_size</code> is a helper that formats an integer value representing bytes into either <code>mb</code>, <code>kb</code> or <code>b</code></li>
</ul>
<p>With this in place, let's add the css for our thumbnails section, <code>IL169 - LL236</code></p>
<h4><a href="#image-preview-component" aria-hidden="true" class="anchor" id="image-preview-component"></a>Image Preview component</h4>
<p>Finally, on <code>image_preview.js</code>:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-javascript" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #dc8ed9;">import</span> <span style="color: #aeafb0;">&lbrace;</span> <span style="color: #dfdfe0;">get_size</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">calc_total_sizes</span> <span style="color: #aeafb0;">&rbrace;</span> <span style="color: #dc8ed9;">from</span> <span style="color: #81b29a;">&quot;../js/utilities.js&quot;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3"><span style="color: #dc8ed9;">export</span> <span style="color: #9d79d6;">default</span> <span style="color: #9d79d6;">function</span> <span style="color: #86abdc;">ImagePreview</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span> <span style="color: #7ad5d6;">state</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">prefix</span><span style="color: #aeafb0;">,</span>  <span style="color: #7ad5d6;">children</span> <span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="4">    <span style="color: #9d79d6;">let</span> <span style="color: #dfdfe0;">prefixed</span> <span style="color: #aeafb0;">=</span> <span style="color: #81b29a;">`$&lbrace;</span><span style="color: #dfdfe0;">prefix</span><span style="color: #7ad5d6;">&rbrace;</span><span style="color: #81b29a;">$&lbrace;</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">selected_image_url</span><span style="color: #7ad5d6;">&rbrace;</span><span style="color: #81b29a;">`</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="5">    
</div><div class="line" data-line="6">    <span style="color: #c94f6d;">return</span> <span style="color: #aeafb0;">(</span>
</div><div class="line" data-line="7">	<span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">div</span> <span style="color: #86abdc;">className</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;image-container-wrapper&quot;</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="8">	  <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">div</span> <span style="color: #86abdc;">className</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;image-info-container&quot;</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="9">	    <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">div</span> <span style="color: #86abdc;">className</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;image-info-size&quot;</span><span style="color: #7ad5d6;">&gt;</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">selected_image_url</span> <span style="color: #baa1e2;">?</span> <span style="color: #86abdc;">get_size</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">prefixed</span><span style="color: #aeafb0;">)</span> <span style="color: #baa1e2;">:</span> <span style="color: #81b29a;">&quot;No info&quot;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">div</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="10">	    <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">div</span> <span style="color: #86abdc;">className</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;image-info-size-total&quot;</span><span style="color: #7ad5d6;">&gt;</span>Total: <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">calc_total_sizes</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">div</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="11">	  <span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">div</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="12">	  <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">div</span> <span style="color: #86abdc;">className</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;image-container&quot;</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="13">            <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">selected_image</span> <span style="color: #baa1e2;">?</span>
</div><div class="line" data-line="14">              <span style="color: #dfdfe0;">children</span> <span style="color: #baa1e2;">:</span>
</div><div class="line" data-line="15">              <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">p</span><span style="color: #7ad5d6;">&gt;</span>Select an Image to preview<span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">p</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="16">	    <span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="17">	  <span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">div</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="18">	<span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">div</span><span style="color: #7ad5d6;">&gt;</span> 	    
</div><div class="line" data-line="19">    <span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="20"><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">;</span>
</div></code></pre>
<p>This one is a simple wrapper. If there's no selected image it shows <code>Select an image to preview</code>, and in case the size of the file hasn't been retrieved yet (it's an async function) it shows <code>No info</code>, if there's a selected image we use the children prop to display it.</p>
<p>Let's add the CSS styling for this part <code>IL239 - LL336</code></p>
<h4><a href="#final-indexjs" aria-hidden="true" class="anchor" id="final-indexjs"></a>Final index.js</h4>
<p>Lastly, we're ready to finish our <code>index.js</code> file (omitting the reducer and initial state) :</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-javascript" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #dc8ed9;">import</span> <span style="color: #dbc074;">Head</span> <span style="color: #dc8ed9;">from</span> <span style="color: #81b29a;">&quot;next/head&quot;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="2"><span style="color: #dc8ed9;">import</span> <span style="color: #dbc074;">Sidebar</span> <span style="color: #dc8ed9;">from</span> <span style="color: #81b29a;">&quot;../components/sidebar.js&quot;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="3"><span style="color: #dc8ed9;">import</span> <span style="color: #dbc074;">ImagePreview</span> <span style="color: #dc8ed9;">from</span> <span style="color: #81b29a;">&quot;../components/image_preview.js&quot;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="4"><span style="color: #dc8ed9;">import</span> <span style="color: #dbc074;">Thumbnails</span> <span style="color: #dc8ed9;">from</span> <span style="color: #81b29a;">&quot;../components/thumbnails.js&quot;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="5"><span style="color: #dc8ed9;">import</span> <span style="color: #dbc074;">Copyright</span> <span style="color: #dc8ed9;">from</span> <span style="color: #81b29a;">&quot;../components/copyright.js&quot;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7"><span style="color: #dc8ed9;">import</span> <span style="color: #aeafb0;">&lbrace;</span> <span style="color: #dbc074;">Image</span> <span style="color: #aeafb0;">&rbrace;</span> <span style="color: #dc8ed9;">from</span> <span style="color: #81b29a;">&quot;@imageengine/react&quot;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="8">
</div><div class="line" data-line="9"><span style="color: #dc8ed9;">import</span> <span style="color: #aeafb0;">&lbrace;</span> <span style="color: #dfdfe0;">useReducer</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">useEffect</span> <span style="color: #aeafb0;">&rbrace;</span> <span style="color: #dc8ed9;">from</span> <span style="color: #81b29a;">&quot;react&quot;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="10">
</div><div class="line" data-line="11"><span style="color: #dc8ed9;">import</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="12">    <span style="color: #dfdfe0;">build_type_key</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="13">    <span style="color: #dfdfe0;">handle_image</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="14">    <span style="color: #f6b079;">NON_OPTIMIZED_ADDRESS</span>
</div><div class="line" data-line="15"><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #dc8ed9;">from</span> <span style="color: #81b29a;">&quot;../js/utilities.js&quot;</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="16">
</div><div class="line" data-line="17">
</div><div class="line" data-line="18"><span style="color: #dc8ed9;">export</span> <span style="color: #9d79d6;">default</span> <span style="color: #9d79d6;">function</span> <span style="color: #86abdc;">Home</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="19">    <span style="color: #9d79d6;">const</span> <span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">dispatch</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">=</span> <span style="color: #86abdc;">useReducer</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">settings_reducer</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">initial_settings_state</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="20">
</div><div class="line" data-line="21">    <span style="color: #86abdc;">useEffect</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="22">	<span style="color: #86abdc;">setTimeout</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #86abdc;">dispatch</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #719cd6;">type</span><span style="color: #aeafb0;">:</span> <span style="color: #81b29a;">&quot;force_load&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #719cd6;">value</span><span style="color: #aeafb0;">:</span> <span style="color: #f4a261;">true</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">25</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="23">    <span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="24">    
</div><div class="line" data-line="25">    <span style="color: #c94f6d;">return</span> <span style="color: #aeafb0;">(</span>
</div><div class="line" data-line="26">	<span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">div</span> <span style="color: #86abdc;">className</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;main-container&quot;</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="27">	  <span style="color: #7ad5d6;">&lt;</span><span style="color: #9d79d6;">Head</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="28">	    <span style="color: #7ad5d6;">&lt;</span>title<span style="color: #7ad5d6;">&gt;</span><span style="color: #86abdc; font-weight: bold;">ImageEngine Optimized Assets</span><span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">title</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="29">	  <span style="color: #7ad5d6;">&lt;/</span><span style="color: #9d79d6;">Head</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="30">	  <span style="color: #7ad5d6;">&lt;</span><span style="color: #9d79d6;">Sidebar</span> <span style="color: #86abdc;">state</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #86abdc;">dispatch</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">dispatch</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #7ad5d6;">/&gt;</span>
</div><div class="line" data-line="31">	  <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">div</span> <span style="color: #86abdc;">className</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;main-area&quot;</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="32">	    <span style="color: #7ad5d6;">&lt;</span>h2 <span style="color: #86abdc;">className</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;page-title&quot;</span><span style="color: #7ad5d6;">&gt;</span><span style="color: #86abdc; font-weight: bold;">ImageEngine (left) vs Unoptimized (right)</span><span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">h2</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="33">	    <span style="color: #7ad5d6;">&lt;</span><span style="color: #9d79d6;">Copyright</span> <span style="color: #86abdc;">state</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #86abdc;">dispatch</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">dispatch</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #7ad5d6;">/&gt;</span>
</div><div class="line" data-line="34">	    <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">div</span> <span style="color: #86abdc;">className</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;main-area-images&quot;</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="35">              <span style="color: #7ad5d6;">&lt;</span><span style="color: #9d79d6;">ImagePreview</span> <span style="color: #86abdc;">state</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #86abdc;">type</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;ie&quot;</span> <span style="color: #86abdc;">prefix</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #81b29a;">&quot;&quot;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="36">                <span style="color: #7ad5d6;">&lt;</span><span style="color: #9d79d6;">Image</span>
</div><div class="line" data-line="37">                  <span style="color: #86abdc;">src</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">selected_image_url</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="38">                  <span style="color: #86abdc;">directives</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="39">                    <span style="color: #719cd6;">outputFormat</span><span style="color: #aeafb0;">:</span> <span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">file_type</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="40">                    <span style="color: #719cd6;">height</span><span style="color: #aeafb0;">:</span> <span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">height</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="41">                    <span style="color: #719cd6;">width</span><span style="color: #aeafb0;">:</span> <span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">width</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="42">                    <span style="color: #719cd6;">fitMethod</span><span style="color: #aeafb0;">:</span> <span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">fit_type</span>
</div><div class="line" data-line="43">                  <span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="44">                  <span style="color: #86abdc;">onLoad</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">event</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #86abdc;">handle_image</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;ie&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">event</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">target</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">selected_image_url</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">dispatch</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="45">                <span style="color: #7ad5d6;">/&gt;</span>
</div><div class="line" data-line="46">              <span style="color: #7ad5d6;">&lt;/</span><span style="color: #9d79d6;">ImagePreview</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="47">              <span style="color: #7ad5d6;">&lt;</span><span style="color: #9d79d6;">ImagePreview</span> <span style="color: #86abdc;">state</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #86abdc;">type</span><span style="color: #aeafb0;">=</span><span style="color: #81b29a;">&quot;regular&quot;</span> <span style="color: #86abdc;">prefix</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #f6b079;">NON_OPTIMIZED_ADDRESS</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="48">                <span style="color: #7ad5d6;">&lt;</span><span style="color: #86abdc;">img</span> <span style="color: #86abdc;">src</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #f6b079;">NON_OPTIMIZED_ADDRESS</span> <span style="color: #aeafb0;">+</span> <span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">selected_image_url</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #86abdc;">onLoad</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">event</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #86abdc;">handle_image</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;regular&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">event</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">target</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">(</span><span style="color: #f6b079;">NON_OPTIMIZED_ADDRESS</span> <span style="color: #aeafb0;">+</span> <span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">.</span><span style="color: #719cd6;">selected_image_url</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">dispatch</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #7ad5d6;">/&gt;</span>
</div><div class="line" data-line="49">              <span style="color: #7ad5d6;">&lt;/</span><span style="color: #9d79d6;">ImagePreview</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="50">	    <span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">div</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="51">	    <span style="color: #7ad5d6;">&lt;</span><span style="color: #9d79d6;">Thumbnails</span> <span style="color: #86abdc;">state</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">state</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #86abdc;">dispatch</span><span style="color: #aeafb0;">=</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">dispatch</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #7ad5d6;">/&gt;</span>
</div><div class="line" data-line="52">	  <span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">div</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="53">	<span style="color: #7ad5d6;">&lt;/</span><span style="color: #86abdc;">div</span><span style="color: #7ad5d6;">&gt;</span>
</div><div class="line" data-line="54">    <span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">;</span>
</div><div class="line" data-line="55"><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">;</span>
</div></code></pre>
<p>Besides the <code>useReducer</code> we also imported <code>useState</code> and used it here:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-javascript" translate="no" tabindex="0"><div class="line" data-line="1">  <span style="color: #86abdc;">useEffect</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="2">    	<span style="color: #86abdc;">setTimeout</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #86abdc;">dispatch</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #719cd6;">type</span><span style="color: #aeafb0;">:</span> <span style="color: #81b29a;">&quot;force_load&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #719cd6;">value</span><span style="color: #aeafb0;">:</span> <span style="color: #f4a261;">true</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">25</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="3">    <span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">;</span>
</div></code></pre>
<p>To show the thumbnails so their <code>onload</code> handle triggers properly.</p>
<p>On the first <code>&lt;ImagePreview&gt;</code> component we pass as a child an ImageEngine <code>Image</code> component, and we set both the <code>src</code> prop to our <code>selected_image_url</code> and the <code>directives</code> prop to an object containing the customisable properties we have in our sidebar. We could add further directives here. Because we wrapped our <code>_app.js</code> content with an <code>&lt;ImageEngineProvider&gt;</code> it will automatically be used by the <code>&lt;Image&gt;</code> component. In a normal situation we might want to debounce the changes to our reducer’s state so it doesn’t immediately request a new image.</p>
<p>In the second <code>&lt;ImagePreview&gt;</code> instead we pass a simple html <code>&lt;img&gt;</code> tag.</p>
<p>If you try to see the website it should be working, but the images won't be loading as we haven't them yet - you can download them from <a href="https://github.com/mnussbaumer/ie-nextjs-sample/tree/main/public/images">images</a> and place them in <code>public/images</code>.
We aren't using yet an actual <code>IE</code> distribution, so we won't have any differences in sizes, except that the IE side will count each image twice as you pick them, once for the thumbnails, another for the previews - as we discussed earlier.</p>
<p>If you want to add responsiveness to the layout, there’s a few more lines of css to add, <code>IL338 - LL372</code>.</p>
<h4><a href="#bucket-ie-distribution-static-build-and-deploying" aria-hidden="true" class="anchor" id="bucket-ie-distribution-static-build-and-deploying"></a>Bucket, IE distribution, static build and deploying</h4>
<p>Now that we have our app ready, let's set up an AWS S3 bucket to host it. In this case we will host it bare on S3, as a static website, making the whole bucket public, but outside of a tutorial, this bucket shouldn't be public at all and instead use cloudfront in front (get it?). You can do it from the aws console interface, or using the aws cli. With the cli, change the <code>bucket-name</code> and <code> use-west-2</code> region to something you want on the following commands:</p>
<p><code>aws s3 mb s3://bucket-name --region us-west-2</code>
<code>aws s3 website s3://bucket-name/ --index-document index.html --error-document 404.html</code></p>
<p>Because we created the bucket in <code>us-west-2</code> region and set it as a static website, it will be hosted on the following url <code>http://bucket-name.s3-website-us-west-2.amazonaws.com</code></p>
<p>If using AWS Console just create a new bucket and set it as a static website after it's created (from the <code>Properties</code> tab),</p>
<p>Now that we have an host we can refer to, let's create an ImageEngine distribution for it:</p>
<p><video width="100%" controls ><source src="https://cdn.imageengine.io/images/docs/IE-signup.mp4" type="video/mp4">Your browser does not support the video tag.</video></p>
<p><a href="https://imageengine.io">imageengine.io</a></p>
<p>changing the url address used in the video to that of your bucket. Then from your account panel, select <code>Edit Engine</code> and on the <code>CORS Support</code> section change the <code>HTTP methods allowed</code> value from <code>GET</code>, to <code>GET,HEAD</code>.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/32xo66dxc7hu2kmor8nf.jpg" alt="setting cors in IE" /></p>
<p>And that’s all for <code>IE</code>. Right now we don't have any files on our bucket so we don't have a website yet. <code>Next.js</code> allows you to build a static website that we can use in <code>S3</code>. Since we have the url for our bucket and for our IE distribution we can build our website using those values.</p>
<p>Let's add a specific command to our <code>package.json</code> that does it for us, under the <code>scripts</code> key, add <code>&quot;static&quot;: &quot;next build &amp;&amp; next export&quot;</code>. Save the file.
From the command line we can now run (substituting the values for the ones you have):</p>
<p><code>DELIVERY_ADDRESS=&quot;https://your-image-engine.cdn.imgeng.in&quot; NON_OPTIMIZED_ADDRESS=&quot;http://bucket-name.s3-website-us-west-2.amazonaws.com&quot; npm run static</code></p>
<p>This will create all necessary files for a static website in the <code>out</code> directory of your app dir. The last step is to upload those files into our bucket. We can do that manually through the console interface, or using the cli:</p>
<p><code>aws s3 cp out s3://bucket-name/ --recursive --acl public-read</code></p>
<p>Notice we need to set the Access Control List to <code>public-read</code>. If doing the upload through the interface we would need to set it on the upload panel, before uploading them.</p>
<p>And that's it, maybe give it a minute and you should be able to visit <code>http://bucket-name.s3-website-us-west-2.amazonaws.com</code> and see it working!</p>
<p>Now that you have the ImageEngine distribution available you can also run it locally with <code>DELIVERY_ADDRESS=&quot;https://your-image-engine.cdn.imgeng.in&quot; npm run dev</code>.</p>
<p>If you omit the <code>DELIVERY_ADDRESS</code> then it will serve the local assets for both parts as it did initially. This is the same if you're integrating ImageEngine into an existing website, you can do all the code changes to use the <code>Image</code> component, while still relying on the normal image urls, and once ready, build a version with the correct <code>DELIVERY_ADDRESS</code> (or if running on a nodejs server restart it with the proper env set). If you’re not using Nextjs, or need some more control on your image components, you can also build the query string for the directives and use it directly in any <code>img</code> element’s <code>src</code>, or in http requests.</p>
<h4><a href="#conclusion" aria-hidden="true" class="anchor" id="conclusion"></a>Conclusion</h4>
<p>It's easy to add <strong>IE</strong> to a website or when starting a new project, as it involves just attaching a query string parameter to your image <code>src</code>'s. In the same way it's also easy to leverage new HTML image attributes, such as <code>srcset/sizes</code> to define particular viewport dimensions with specific optimisations, as again, it just requires a query string.</p>
<p>If you're serving a significant amount of images and you don't have an image optimisation pipeline in place, need finer grain control than things like <code>Next.js</code> image optimisations, aren't running a <code>Nodejs</code> web server, or don't want to worry about that part of your infrastructure, then <code>IE</code> makes a lot of sense - its <code>CDN</code> is <strong>really fast</strong> as is their on-the-fly transformation engine - on top of that given their work on adjacent areas - <em>device display identification</em> - any improvements to their algorithms are automatically applied to your existing sources, and new options when available easily integrated.</p> ]]></description>
    </item>
    <item>
       <title>Writing the basis of an HTML Server with Elixir</title>
       <link>https://micaelnussbaumer.com/posts/writing-a-html-server-in-elixir/</link>
       <pubDate>Sat, 14 Sep 2019 16:55:26 UTC</pubDate>
       <guid>https://micaelnussbaumer.com/posts/writing-a-html-server-in-elixir/</guid>
       <description><![CDATA[ <p>Building a basic http server in Elixir.</p>
<p>I've been writing an http server in Erlang, which is still far from finished but coming together slowly, as a way of learning more in depth the http protocol and how to deal with it from scratch.</p>
<p>To write down my findings and share them I decided I should write a post on how to do that and in the process show some very neat more lowlevel aspects of erlang. There's a good range of http server libs available in Erlang, if you use Phoenix you'll be using Cowboy underneath, each one with its own design decisions, all of them pretty fine.</p>
<p>We won't be tackling in this post websockets nor any proper http connection upgrades, http2 and such, that will be hopefully for future posts, but instead we'll see how to create a simple socket acceptor pool, use gen_statems to create a way to run a &quot;pipeline&quot;, design a basic router, parse the incoming requests, etc.</p>
<p>You can find the final source code for this at <a href="https://github.com/mnussbaumer/satellitex">satellitex repo</a> up to the end of the tutorial.</p>
<p>We'll have at least 4 components:</p>
<ul>
<li>the socket acceptor pool - creates a number of ready to work socket listeners waiting for requests on a given port</li>
<li>the gen_statem that will use a modular and exchangeable pipeline definition to parse the request and route it appropriately</li>
<li>the router module that allows a custom DSL that generates a proper router for our gen_statem to call with the appropriate routes and data</li>
<li>a response creator, to send the responses to our clients when they visit our website</li>
</ul>
<p>We'll also need several parsing functions.</p>
<p>To follow along you need to have installed erlang 22 and elixir 1.9 (compiled with erlang 22). After having those installed, lets start by creating an umbrella app, from the command line:</p>
<p><code>mix new satellitex --umbrella</code></p>
<p>Lets go into our newly created directory and further into the <code>apps</code> folder and create our socket acceptor app (it will be a simple lib and not an application with a supervision tree):</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-bash" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #c94f6d;">cd</span> <span style="color: #7ad5d6;">satellitex/apps</span>
</div><div class="line" data-line="2"><span style="color: #86abdc;">mix</span> <span style="color: #7ad5d6;">new</span> <span style="color: #7ad5d6;">launchpad</span> 
</div></code></pre>
<p>Now we'll be using gen_statem and so we should add some key properties to our logger configuration so that we can get system reports if the gen_statem crashes, otherwise we won't see the actual errors caused by it since <code>Logger</code> by default doesn't output system logs unless told to do so and gen_statem outputs its errors as system reports. Lets open our <code>config.exs</code> file for the umbrella (<code>satellitex/config/config.exs</code>) and make it look like the following:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">use</span> <span style="color: #7ad5d6;">Mix.Config</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3"><span style="color: #86abdc;">import_config</span> <span style="color: #81b29a;">&quot;../apps/*/config/config.exs&quot;</span>
</div><div class="line" data-line="4">
</div><div class="line" data-line="5"><span style="color: #86abdc;">config</span> <span style="color: #86abdc;">:logger</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="6">  <span style="color: #86abdc;">handle_otp_reports: </span><span style="color: #f4a261;">true</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="7">  <span style="color: #86abdc;">handle_sasl_reports: </span><span style="color: #f4a261;">true</span>
</div></code></pre>
<p>Now save the file. This is not to say that our code will have errors, that's quite outrageous to even think, but just in case we mistyped something.</p>
<p>Let's start writing our acceptor. This will be our &quot;server&quot; per se. It won't deal with requests by itself, instead, what it will do is open a socket in a given <code>port</code> and then create any number of ready to fire acceptors, listening on the socket. Each acceptor will be itself an independent process, to which we give &quot;control&quot; of the request as soon as a tcp connection is open, so that they can read from the socket and parse the request into something structured and usable for our application. We'll dive into that shortly after, but the idea is that it will be able to accept a &quot;pipeline&quot; definition and process the request according to that pipeline so that it's easily extendable.</p>
<p>First, if you never used the <code>gen_statem</code> OTP behaviour it's a fairly useful abstraction. It's similar to <code>gen_servers</code>, but it's newer and requires a bit more ceremony. <code>gen_server</code>s, due to having been there for so long and having a very simple layout are used much more often but lately I've been finding that gen_statems are really nice to use in a lot of different situations, even if you're not writing anything that is a complex state machine, whenever you may have state transitions it fits very well (I already used continue handles a lot in <code>gen_server</code>s and now I think they're the poor man's version of a gen_statem).</p>
<p>They're a behaviour, so we need to declare that, and they can operate in two different modes of callback, <code>state_function</code>s or <code>handle_event_function</code>s. We'll use handle_events mode, but to just cover the differences, in handle event mode you write every callback as <code>def handle_event(........) end</code> and the state can be as complex as you want. In <code>state_function</code> mode you write functions where the name of the function is the <code>state</code> to which it refers and the state must always be an atom. So if you had a <code>state</code> of <code>starting</code>, you would have a <code>def starting(.....) end</code> function(s) to handle all events when the state machine is in that state and other similarly named functions for each state you have. I personally like better the handle mode.</p>
<p>Our ideal server will accept a bunch of settings to decide how to start itself, it will have a start_link function that receives these options, then call a init function with these options that opens up the socket and starts the acceptors.</p>
<p>So let's go to our launchpad application, and open <code>/apps/launchpad/lib/launchpad.ex</code> and replace it with the following:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Launchpad</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">    <span style="color: #f6b079;">@</span><span style="color: #f6b079;">behaviour </span><span style="color: #86abdc;">:gen_statem</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4">    <span style="color: #9d79d6;">defstruct</span> <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:socket</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:config</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">max_pool: </span><span style="color: #f4a261;">5</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">pool_count: </span><span style="color: #f4a261;">0</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">acceptors: </span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="5">   
</div><div class="line" data-line="6">    <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">start_link</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">opts</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="7">        <span style="color: #dfdfe0;">name</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">get</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">opts</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:name</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:local</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">__MODULE__</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="8">    
</div><div class="line" data-line="9">        <span style="color: #dbc074;">:gen_statem</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">start_link</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">name</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">__MODULE__</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">opts</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="10">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="11">
</div><div class="line" data-line="12">    <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #f4a261;">true</span>
</div><div class="line" data-line="13">    <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">callback_mode</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:handle_event_function</span>
</div><div class="line" data-line="14">
</div><div class="line" data-line="15">    <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #f4a261;">true</span>
</div><div class="line" data-line="16">    <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">init</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">opts</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="17">        <span style="color: #7ad5d6;">Process</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">flag</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:trap_exit</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">true</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="18">    
</div><div class="line" data-line="19">        <span style="color: #dfdfe0;">port</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">get</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">opts</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:port</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">4000</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="20">    
</div><div class="line" data-line="21">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">socket</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dbc074;">:gen_tcp</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">listen</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">port</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:binary</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:packet</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:raw</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:active</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">false</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:reuseaddr</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">true</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="22">
</div><div class="line" data-line="23">    <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">%</span><span style="color: #f6b079;">__MODULE__</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">socket: </span><span style="color: #dfdfe0;">socket</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">config: </span><span style="color: #dfdfe0;">opts</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="24">    
</div><div class="line" data-line="25">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:starting</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:create_listener</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="26">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="27">
</div><div class="line" data-line="28">    <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #f4a261;">true</span>
</div><div class="line" data-line="29">    <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:create_listener</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_state</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="30">        <span style="color: #7ad5d6;">%</span><span style="color: #f6b079;">__MODULE__</span><span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="31">            <span style="color: #86abdc;">socket: </span><span style="color: #dfdfe0;">socket</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="32">            <span style="color: #86abdc;">config: </span><span style="color: #dfdfe0;">config</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="33">            <span style="color: #86abdc;">max_pool: </span><span style="color: #dfdfe0;">max</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="34">            <span style="color: #86abdc;">pool_count: </span><span style="color: #dfdfe0;">pc</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="35">            <span style="color: #86abdc;">acceptors: </span><span style="color: #dfdfe0;">acceptors</span>
</div><div class="line" data-line="36">        <span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span>
</div><div class="line" data-line="37">    <span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #dfdfe0;">pc</span> <span style="color: #aeafb0;">&lt;</span> <span style="color: #dfdfe0;">max</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="38">    
</div><div class="line" data-line="39">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">pid</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Satellite</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">start_link</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">socket</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">config</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:number</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">pc</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="40">        <span style="color: #dfdfe0;">n_acceptors</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acceptors</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">pid</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">true</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="41">
</div><div class="line" data-line="42">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:keep_state</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">pool_count: </span><span style="color: #dfdfe0;">pc</span> <span style="color: #aeafb0;">+</span> <span style="color: #f4a261;">1</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">acceptors: </span><span style="color: #dfdfe0;">n_acceptors</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:create_listener</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="43">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="44">
</div><div class="line" data-line="45">    <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:create_listener</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:starting</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:running</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="46">
</div><div class="line" data-line="47">    <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:create_listener</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_state</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_data</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:keep_state_and_data</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="48">
</div><div class="line" data-line="49">    <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:info</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:EXIT</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">pid</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_reason</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">pool_count: </span><span style="color: #dfdfe0;">pc</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">acceptors: </span><span style="color: #dfdfe0;">acceptors</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #dbc074;">:erlang</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">is_map_key</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">pid</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acceptors</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="50">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_acceptors</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">pop</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acceptors</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">pid</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="51">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:keep_state</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">pool_count: </span><span style="color: #dfdfe0;">pc</span> <span style="color: #aeafb0;">-</span> <span style="color: #f4a261;">1</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">acceptors: </span><span style="color: #dfdfe0;">n_acceptors</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:create_listener</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="52">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="53">
</div><div class="line" data-line="54">    <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:info</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:EXIT</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">pid</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">reason</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="55">        <span style="color: #7ad5d6;">IO</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">puts</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;Received exit from unknown process </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span> <span style="color: #dfdfe0;">pid</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;"> with reason </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #dfdfe0;">reason</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">)</span>	
</div><div class="line" data-line="56">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:keep_state_and_data</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="57">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="58">
</div><div class="line" data-line="59"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>There's quite a lot going on there so let's break it up:</p>
<ul>
<li><code>@behaviour :gen_statem</code> - we're simply stating that this module will implement the <code>:gen_statem</code> OTP behaviour</li>
<li><code>defstruct ....</code> - a structure we created to hold the relevant information about our server, it has a few keys, <code>:socket</code>, which will hold the socket ref once we open it, <code>:config</code>, which will store the configuration passed to it, <code>:max_pool</code>, which is the maximum number of acceptors we want to have running at each time, <code>:pool_count</code>, just a counter that holds how many acceptors we have running to decide if we need to start more or not, and <code>:acceptors</code> were we keep a map of our acceptors pids</li>
<li><code>def callback_mode()</code> - it's a required function for this behaviour and it informs what type of callbacks our <code>:gen_statem</code> will be running, in this case we set it to return <code>:handle_event_function</code></li>
</ul>
<p>The others are regular things, a <code>start_link/1</code> function that takes an argument (which will be a map/struct with configuration) a <code>init/1</code> function that the behaviour requires to start, in our case the argument will be the same as passed down to start_link, and then two <code>handle_event</code> functions, these are functions defining the behaviour of our :gen_statem and how it should act when there's either a state change or an event trigger.</p>
<p>In the <code>start_link/1</code>, for now, we will just try to get a key <code>:name</code> from it in order to register our process. In case no <code>name</code> is provided we default to <code>&lbrace;:local, __MODULE__&rbrace;</code>, which will register our process locally, on start, as <code>Launchpad</code> (that's what <code>__MODULE__</code> gets translated to).</p>
<p>So for <code>:gen_statem.start_link(name, __MODULE__, opts, [])</code>, the first argument is the name to register, the second is the module implementing the statem (in this case it's this module itself), the 3rd is the arguments passed to <code>init/1</code> and the 4th is a list of keyword options for the :gen_statem initialization itself, that we're leaving empty. We could also make <code>gen_statem</code> anonymous by excluding the 1st argument.</p>
<p>On the <code>init/1</code> function we're setting the process to trap exits by using <code>Process.flag(:trap_exit, true)</code>, the reason for this is because we'll be starting each acceptor as a link, so that if our &quot;launchpad&quot; process dies they are killed as well, but in turn, because links are bi-directional, this makes it so that if any of the acceptors dies our &quot;launchpad&quot; would too. Since we set it to trap exits, instead, if an acceptor dies, what will happen is we will receive a message telling us about it, this will allow us to &quot;know&quot; when one of them goes down in case we want to start another one to replace it, instead of it simply exiting automatically.</p>
<p>Then we read the port from the config or default to <code>4000</code> and next we start the actual socket process listening on that port, with a bunch of options through <code>:gen_tcp.listen</code>.</p>
<p>The options we pass are <code>:binary</code>, telling we want to read the socket as binary segments, we set <code>&lbrace;:active, false&rbrace;</code>, this means that we don't want to read data immediately whenever it arrives, we want to control how and when the reading is going to happen. :reuseaddr is for the socket to allow reusing the same address and <code>&lbrace;:packet, :raw&rbrace;</code>, tells to pass the data as read. If the <code>:gen_tcp.listen</code> succeeds it means we were able to bind to that socket port, otherwise this will raise an error, crash, and if the user of our server started it from a supervisor hopefully crash their app, so that they notice something is wrong.</p>
<p>Then we just create a struct for our data, with the previously opened socket and the config map passed to it.</p>
<p>The <code>init/1</code> callback has to return when successful an <code>&lbrace;:ok, ...statem_definitions&rbrace;</code> tuple, in our case:</p>
<p><code>&lbrace;:ok, :starting, data, [&lbrace;:next_event, :internal, :create_listener&rbrace;]&rbrace;</code></p>
<p>Means, set the internal initial state to <code>:starting</code> and the statem data as the contents of <code>data</code>. The last element is a list of actions specific to the :gen_statem behaviour that dictate any event it should trigger upon finishing this callback. In this case we say, we want to trigger a new event, a specific internal one that we can be sure is only triggered from our gen_statem, with the name <code>:create_listener</code>.</p>
<p>Hence the next <code>handle_event</code> functions we wrote. Each handle_event function receives as its arguments:</p>
<p><code>type_of_event</code>, <code>event</code>, <code>currrent_state</code>, <code>current_data</code></p>
<p>The type of event can be <code>:internal</code>, <code>:info</code>, <code>:call</code>, <code>:cast</code>, <code>:timeout</code>, etc... You can find all the documentation for gen_statem in <a href="http://erlang.org/doc/man/gen_statem.html">erlang documentation</a> The event is the contents of that event, and the others are self explanatory. An <code>:internal</code> event type can only be issued by your own code inside the gen_statem where they happen, you can be sure these were generated by you.</p>
<p>On the first <code>handle_event</code> we pattern match on our struct specifically so we can access the value of <code>:max_pool</code> and <code>:pool_count</code>. This way we can know if the maximum number of acceptors are already running or not, and we do that by setting a guard clause, <code>when pc &lt; max</code>.</p>
<p>So if the pool_count is lower than the max we have set, then open a new one, otherwise the next function head that matches will be the one called - we have two, one if we're in the <code>:starting</code> state, which will just switch to the state <code>:running</code> while keeping everything else, and another one that matches whenever the state is not starting and the max acceptors have already been created, it does nothing by returning <code>&lbrace;:keep_state_and_data, []&rbrace;</code>, which is a shorthand for <code>&lbrace;:next_state, :same_state, same_data, []&rbrace;</code>.</p>
<p>When we create a new listener, we increment the pool count, we add that pid as a key to our <code>acceptors</code> map and we trigger the same event again.
So it repeats the listener creation until we have the max number of acceptors created and then sits waiting, doing a siesta.</p>
<p>Lastly we have a function to receive the <code>EXIT</code> message in case any of our linked processes dies, because we're trapping exits. When we receive one we decrease the pool count by one and  trigger a new event to create another listener. We know this exit is from an &quot;acceptor&quot; process because we use the guard <code>:erlang.is_map_key(acceptors, pid)</code>, basically saying only match this function when the pid on the <code>EXIT</code> message is a key on the map <code>acceptors</code>, meaning one of the pids from an acceptor we started (that we know because we placed them in the acceptors map as keys). If it's not we do a naive log of it because we should theoretically not have received that exit signal.</p>
<p>So our app is actually a library, this is because we don't want to control how it's started from itself, instead we expose the <code>start_link/1</code> function that then someone can start on their own supervisor trees. We'll see that later but, for now, lets see if it does something already.  Go to the root of the umbrella and start an iex shell, with:</p>
<p><code>iex -S mix run</code></p>
<p>You should see some warnings, and:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #7ad5d6;">Erlang</span><span style="color: #aeafb0;">/</span><span style="color: #7ad5d6;">OTP</span> <span style="color: #f4a261;">22</span> <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">erts</span><span style="color: #aeafb0;">-</span><span style="color: #f4a261;">10.4</span><span style="color: #aeafb0;">.</span><span style="color: #f4a261;">3</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">source</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">[</span><span style="color: #f4a261;">64</span><span style="color: #aeafb0;">-</span><span style="color: #dfdfe0;">bit</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">smp</span>:<span style="color: #f4a261;">8</span>:<span style="color: #f4a261;">8</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">ds</span>:<span style="color: #f4a261;">8</span>:<span style="color: #f4a261;">8</span>:<span style="color: #f4a261;">10</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">async</span><span style="color: #aeafb0;">-</span><span style="color: #86abdc;">threads</span>:<span style="color: #f4a261;">1</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">hipe</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3"><span style="color: #aeafb0;">==</span><span style="color: #aeafb0;">&gt;</span> launchpad
</div><div class="line" data-line="4">C<span style="color: #86abdc;">ompiling</span> <span style="color: #f4a261;">1</span> <span style="color: #86abdc;">file</span> <span style="color: #aeafb0;">(</span>.<span style="color: #dfdfe0;">ex</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="5"><span style="color: #86abdc;">warning</span>: <span style="color: #86abdc;">function</span> <span style="color: #7ad5d6;">Satellite</span><span style="color: #aeafb0;">.</span><span style="color: #dfdfe0;">start_link</span><span style="color: #aeafb0;">/</span><span style="color: #f4a261;">2</span> <span style="color: #86abdc;">is</span> <span style="color: #86abdc;">undefined</span> <span style="color: #aeafb0;">(</span><span style="color: #86abdc;">module</span> <span style="color: #7ad5d6;">Satellite</span> <span style="color: #86abdc;">is</span> <span style="color: #aeafb0;">not</span> <span style="color: #dfdfe0;">available</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="6">  <span style="color: #dfdfe0;">lib</span><span style="color: #aeafb0;">/</span><span style="color: #dfdfe0;">launchpad</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">ex</span>:<span style="color: #f4a261;">39</span>
</div><div class="line" data-line="7">
</div><div class="line" data-line="8">
</div><div class="line" data-line="9"><span style="color: #f4a261;">19</span>:<span style="color: #f4a261;">02</span>:<span style="color: #f4a261;">57.776</span> <span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">info</span><span style="color: #aeafb0;">]</span>  Application <span style="color: #86abdc;">logger</span> <span style="color: #86abdc;">started</span> <span style="color: #86abdc;">at</span> <span style="color: #86abdc;">:nonode@nohost</span>
</div><div class="line" data-line="10"> 
</div><div class="line" data-line="11"><span style="color: #f4a261;">19</span>:<span style="color: #f4a261;">02</span>:<span style="color: #f4a261;">57.776</span> <span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">info</span><span style="color: #aeafb0;">]</span>  Application <span style="color: #86abdc;">launchpad</span> <span style="color: #86abdc;">started</span> <span style="color: #86abdc;">at</span> <span style="color: #86abdc;">:nonode@nohost</span>
</div></code></pre>
<p>We can see already a problem, we don't have a <code>Satellite.start_link/2</code> function neither a <code>Satellite</code> module, and if we try to start our <code>Launchpad</code> we see that error actually happening:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #86abdc;">iex</span><span style="color: #aeafb0;">(</span><span style="color: #f4a261;">1</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&gt;</span> <span style="color: #7ad5d6;">Launchpad</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">start_link</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="2"><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">#PID&lt;0.151.0&gt;&rbrace;</span>
</div><div class="line" data-line="3"><span style="color: #86abdc;">iex</span><span style="color: #aeafb0;">(</span><span style="color: #f4a261;">2</span><span style="color: #aeafb0;">)</span>&gt; 
</div><div class="line" data-line="4"><span style="color: #f4a261;">19</span>:<span style="color: #f4a261;">05</span>:<span style="color: #f4a261;">14.065</span> <span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">error</span><span style="color: #aeafb0;">]</span> Process Launchpad <span style="color: #aeafb0;">(</span><span style="color: #738091;">#PID&lt;0.151.0&gt;) terminating</span>
</div><div class="line" data-line="5"><span style="color: #aeafb0;">**</span> <span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">UndefinedFunctionError</span><span style="color: #aeafb0;">)</span> <span style="color: #86abdc;">function</span> <span style="color: #7ad5d6;">Satellite</span><span style="color: #aeafb0;">.</span><span style="color: #dfdfe0;">start_link</span><span style="color: #aeafb0;">/</span><span style="color: #f4a261;">2</span> <span style="color: #86abdc;">is</span> <span style="color: #86abdc;">undefined</span> <span style="color: #aeafb0;">(</span><span style="color: #86abdc;">module</span> <span style="color: #7ad5d6;">Satellite</span> <span style="color: #86abdc;">is</span> <span style="color: #aeafb0;">not</span> <span style="color: #dfdfe0;">available</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="6">    <span style="color: #7ad5d6;">Satellite</span><span style="color: #aeafb0;">.</span><span style="color: #dfdfe0;">start_link</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">#Port&lt;0.8&gt;, %&lbrace;number: 0&rbrace;)</span>
</div><div class="line" data-line="7">    <span style="color: #86abdc;">...</span><span style="color: #aeafb0;">..</span>
</div></code></pre>
<p>But the <code>Launchpad</code> did start and effectively tried to start one acceptor. Lets write the first completely barebones version of the acceptor.</p>
<p>Lets navigate again to <code>apps/</code> dir, and do:</p>
<p><code>mix new satellite</code></p>
<p>Now let's open <code>apps/satellite/lib/satellite.ex</code></p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Satellite</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">behaviour </span><span style="color: #86abdc;">:gen_statem</span>
</div><div class="line" data-line="3">  
</div><div class="line" data-line="4">  <span style="color: #9d79d6;">defstruct</span> <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:socket</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:config</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:conn</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">pipeline: </span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">request: </span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="5">   
</div><div class="line" data-line="6">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">start_link</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">socket</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">opts</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="7">    <span style="color: #dbc074;">:gen_statem</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">start_link</span><span style="color: #aeafb0;">(</span><span style="color: #f6b079;">__MODULE__</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">socket</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">opts</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="8">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="9">
</div><div class="line" data-line="10">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #f4a261;">true</span>
</div><div class="line" data-line="11">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">callback_mode</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:handle_event_function</span>
</div><div class="line" data-line="12">  
</div><div class="line" data-line="13">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #f4a261;">true</span>
</div><div class="line" data-line="14">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">init</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">socket</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">config</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="15">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:waiting</span><span style="color: #aeafb0;">,</span>  <span style="color: #7ad5d6;">%</span><span style="color: #f6b079;">__MODULE__</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">socket: </span><span style="color: #dfdfe0;">socket</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">config: </span><span style="color: #dfdfe0;">config</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:wait</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="16">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="17">
</div><div class="line" data-line="18">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #f4a261;">true</span>
</div><div class="line" data-line="19">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:wait</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:waiting</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">socket: </span><span style="color: #dfdfe0;">socket</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="20">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dbc074;">:gen_tcp</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">accept</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">socket</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="21">    
</div><div class="line" data-line="22">    <span style="color: #dbc074;">:gen_tcp</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">controlling_process</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">self</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="23">
</div><div class="line" data-line="24">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:parsing</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">conn: </span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:read</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="25">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="26">
</div><div class="line" data-line="27">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:read</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:parsing</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">conn: </span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="28">    <span style="color: #9d79d6;">case</span> <span style="color: #dbc074;">:gen_tcp</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">recv</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">0</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">1000</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="29">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">packet</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="30">        <span style="color: #7ad5d6;">IO</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">inspect</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">packet</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">label: </span><span style="color: #81b29a;">&quot;received&quot;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="31">        <span style="color: #dfdfe0;">n_data</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">packet</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="32">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:response</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_data</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:send_response</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="33">
</div><div class="line" data-line="34">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:error</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">reason</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="35">        <span style="color: #7ad5d6;">IO</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">inspect</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">reason</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">label: </span><span style="color: #81b29a;">&quot;error on recv&quot;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="36">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:keep_state</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:close</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="37">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="38">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="39">
</div><div class="line" data-line="40">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:send_response</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:response</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">conn: </span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="41">     <span style="color: #dfdfe0;">b</span> <span style="color: #aeafb0;">=</span> <span style="color: #dbc074;">:erlang</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">iolist_to_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="42">     <span style="color: #dfdfe0;">response</span> <span style="color: #aeafb0;">=</span> <span style="color: #dbc074;">:io_lib</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">fwrite</span><span style="color: #aeafb0;">(</span>
</div><div class="line" data-line="43">       <span style="color: #81b29a;">&quot;HTTP/1.0 200 OK</span><span style="color: #e0c989; font-weight: bold;">\n</span><span style="color: #81b29a;">Content-Type: text/html</span><span style="color: #e0c989; font-weight: bold;">\n</span><span style="color: #81b29a;">Content-Length: ~p</span><span style="color: #e0c989; font-weight: bold;">\n</span><span style="color: #e0c989; font-weight: bold;">\n</span><span style="color: #81b29a;">~s&quot;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="44">       <span style="color: #aeafb0;">[</span><span style="color: #dbc074;">:erlang</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">size</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">b</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">b</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="45">     <span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="46">
</div><div class="line" data-line="47">     <span style="color: #dbc074;">:gen_tcp</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">send</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">response</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="48">
</div><div class="line" data-line="49">     <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:keep_state</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:close</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="50">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="51">
</div><div class="line" data-line="52">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:close</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">conn: </span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="53">    <span style="color: #dbc074;">:gen_tcp</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">close</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="54">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:waiting</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">conn: </span><span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">request: </span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:wait</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="55">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="56">
</div><div class="line" data-line="57"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>This is nowhere close to what we want, but it will allow us to already receive http requests. Lets see that and then go through the code. Go to the root of your umbrella on the terminal and again run <code>iex -S mix run</code></p>
<p>Inside the shell now do:</p>
<p><code>Launchpad.start_link(%&lbrace;&rbrace;)</code></p>
<p>You should see <code>&lbrace;:ok, #PID....&rbrace;</code></p>
<p>Now open a browser and visit <code>http://localhost:4000</code>.</p>
<p>Voilá, we have a &quot;server&quot; listening on port 4000. It doesn't do really anything, it just echoes whatever was the request as a <code>text/html</code> response.</p>
<p>To confirm that indeed we have 5 acceptors currently running, let's change this line:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:read</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:parsing</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">conn: </span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">    <span style="color: #9d79d6;">case</span> <span style="color: #dbc074;">:gen_tcp</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">recv</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">0</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">1000</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="3">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">packet</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="4">        <span style="color: #7ad5d6;">IO</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">inspect</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">packet</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">label: </span><span style="color: #81b29a;">&quot;received&quot;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="5">        <span style="color: #dfdfe0;">n_data</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">packet</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="6">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:response</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_data</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:send_response</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="7">
</div><div class="line" data-line="8">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:error</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">reason</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="9">        <span style="color: #7ad5d6;">IO</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">inspect</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">reason</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">label: </span><span style="color: #81b29a;">&quot;error on recv&quot;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="10">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:keep_state</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:close</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="11">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="12"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>To:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:read</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:parsing</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">conn: </span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">config: </span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">number: </span><span style="color: #dfdfe0;">number</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">    <span style="color: #9d79d6;">case</span> <span style="color: #dbc074;">:gen_tcp</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">recv</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">0</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">1000</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="3">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">packet</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="4">        <span style="color: #7ad5d6;">IO</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">inspect</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">packet</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">label: </span><span style="color: #81b29a;">&quot;received&quot;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="5">        <span style="color: #dfdfe0;">n_data</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">packet</span> <span style="color: #aeafb0;">&lt;&gt;</span> <span style="color: #81b29a;">&quot;</span><span style="color: #e0c989; font-weight: bold;">\n</span><span style="color: #e0c989; font-weight: bold;">\n</span><span style="color: #81b29a;">Acceptor number: </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #dfdfe0;">number</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="6">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:response</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_data</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:send_response</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="7">
</div><div class="line" data-line="8">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:error</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">reason</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="9">        <span style="color: #7ad5d6;">IO</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">inspect</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">reason</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">label: </span><span style="color: #81b29a;">&quot;error on recv&quot;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="10">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:keep_state</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:close</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="11">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="12"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Save the file and on the iex shell run <code>recompile()</code>.</p>
<p>Now visit the browser and refresh the page some times. You should see the acceptor changing as you do. Which means that each request you're sending from the browser is being answered by a different process altogether.</p>
<p>If you look in the shell you should also be seeing the output from the <code>IO.inspect</code> functions we placed.</p>
<p>So this string you're seeing will vary depending on the browser, but it will have a structure that is the same. Using Safari I see this:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #7ad5d6;">GET</span> <span style="color: #aeafb0;">/</span> <span style="color: #7ad5d6;">HTTP</span><span style="color: #aeafb0;">/</span><span style="color: #f4a261;">1.1</span>\r\<span style="color: #86abdc;">nHost: </span><span style="color: #86abdc;">localhost</span>:<span style="color: #f4a261;">4000</span>\r\<span style="color: #86abdc;">nConnection: </span><span style="color: #dfdfe0;">keep</span><span style="color: #aeafb0;">-</span><span style="color: #86abdc;">alive</span>\r\<span style="color: #86abdc;">nCache</span><span style="color: #aeafb0;">-</span><span style="color: #7ad5d6;">Control</span>: max<span style="color: #aeafb0;">-</span><span style="color: #dfdfe0;">age</span><span style="color: #aeafb0;">=</span><span style="color: #f4a261;">0</span>\r\<span style="color: #dfdfe0;">nUpgrade</span><span style="color: #aeafb0;">-</span><span style="color: #7ad5d6;">Insecure</span><span style="color: #aeafb0;">-</span><span style="color: #7ad5d6;">Requests</span>: <span style="color: #f4a261;">1</span>\r\<span style="color: #86abdc;">nUser</span><span style="color: #aeafb0;">-</span><span style="color: #7ad5d6;">Agent</span>: Mozilla<span style="color: #aeafb0;">/</span><span style="color: #f4a261;">5.0</span> <span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">Macintosh</span><span style="color: #aeafb0;">;</span> <span style="color: #7ad5d6;">Intel</span> Mac OS X <span style="color: #f4a261;">10_13_6</span><span style="color: #aeafb0;">)</span> AppleWebKit<span style="color: #aeafb0;">/</span><span style="color: #f4a261;">537.36</span> <span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">KHTML</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">like</span> <span style="color: #7ad5d6;">Gecko</span><span style="color: #aeafb0;">)</span> Chrome<span style="color: #aeafb0;">/</span><span style="color: #f4a261;">76.0</span><span style="color: #aeafb0;">.</span><span style="color: #f4a261;">3809.132</span> Safari<span style="color: #aeafb0;">/</span><span style="color: #f4a261;">537.36</span>\r\<span style="color: #dfdfe0;">nSec</span><span style="color: #aeafb0;">-</span><span style="color: #7ad5d6;">Fetch</span><span style="color: #aeafb0;">-</span><span style="color: #7ad5d6;">Mode</span>: <span style="color: #86abdc;">navigate</span>\r\<span style="color: #dfdfe0;">nSec</span><span style="color: #aeafb0;">-</span><span style="color: #7ad5d6;">Fetch</span><span style="color: #aeafb0;">-</span><span style="color: #7ad5d6;">User</span>: <span style="color: #81b29a;">?1</span>\r\<span style="color: #86abdc;">nDNT: </span><span style="color: #f4a261;">1</span>\r\<span style="color: #86abdc;">nAccept: </span><span style="color: #dfdfe0;">text</span><span style="color: #aeafb0;">/</span><span style="color: #dfdfe0;">html</span><span style="color: #aeafb0;">,</span><span style="color: #dfdfe0;">application</span><span style="color: #aeafb0;">/</span><span style="color: #dfdfe0;">xhtml</span><span style="color: #aeafb0;">+</span><span style="color: #dfdfe0;">xml</span><span style="color: #aeafb0;">,</span><span style="color: #dfdfe0;">application</span><span style="color: #aeafb0;">/</span><span style="color: #dfdfe0;">xml</span><span style="color: #aeafb0;">;</span><span style="color: #dfdfe0;">q</span><span style="color: #aeafb0;">=</span><span style="color: #f4a261;">0.9</span><span style="color: #aeafb0;">,</span><span style="color: #dfdfe0;">image</span><span style="color: #aeafb0;">/</span><span style="color: #dfdfe0;">webp</span><span style="color: #aeafb0;">,</span><span style="color: #dfdfe0;">image</span><span style="color: #aeafb0;">/</span><span style="color: #dfdfe0;">apng</span><span style="color: #aeafb0;">,</span>*<span style="color: #aeafb0;">/</span>*<span style="color: #aeafb0;">;</span><span style="color: #dfdfe0;">q</span><span style="color: #aeafb0;">=</span><span style="color: #f4a261;">0.8</span><span style="color: #aeafb0;">,</span><span style="color: #dfdfe0;">application</span><span style="color: #aeafb0;">/</span><span style="color: #dfdfe0;">signed</span><span style="color: #aeafb0;">-</span><span style="color: #dfdfe0;">exchange</span><span style="color: #aeafb0;">;</span><span style="color: #dfdfe0;">v</span><span style="color: #aeafb0;">=</span><span style="color: #86abdc;">b3</span>\r\<span style="color: #dfdfe0;">nSec</span><span style="color: #aeafb0;">-</span><span style="color: #7ad5d6;">Fetch</span><span style="color: #aeafb0;">-</span><span style="color: #7ad5d6;">Site</span>: none\r\<span style="color: #86abdc;">nAccept</span><span style="color: #aeafb0;">-</span><span style="color: #7ad5d6;">Encoding</span>: gzip<span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">deflate</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">br</span>\r\<span style="color: #86abdc;">nAccept</span><span style="color: #aeafb0;">-</span><span style="color: #7ad5d6;">Language</span>: pt<span style="color: #aeafb0;">-</span><span style="color: #7ad5d6;">PT</span><span style="color: #aeafb0;">,</span><span style="color: #dfdfe0;">pt</span><span style="color: #aeafb0;">;</span><span style="color: #dfdfe0;">q</span><span style="color: #aeafb0;">=</span><span style="color: #f4a261;">0.9</span><span style="color: #aeafb0;">,</span><span style="color: #dfdfe0;">en</span><span style="color: #aeafb0;">-</span><span style="color: #7ad5d6;">US</span><span style="color: #aeafb0;">;</span><span style="color: #dfdfe0;">q</span><span style="color: #aeafb0;">=</span><span style="color: #f4a261;">0.8</span><span style="color: #aeafb0;">,</span>en<span style="color: #aeafb0;">;</span><span style="color: #dfdfe0;">q</span><span style="color: #aeafb0;">=</span><span style="color: #f4a261;">0.7</span>\r\n\r\n<span style="color: #81b29a;">&quot;
</div><div class="line" data-line="2">received: &quot;</span>GET <span style="color: #aeafb0;">/</span><span style="color: #dfdfe0;">favicon</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">ico</span> <span style="color: #7ad5d6;">HTTP</span><span style="color: #aeafb0;">/</span><span style="color: #f4a261;">1.1</span>\r\<span style="color: #86abdc;">nHost: </span><span style="color: #86abdc;">localhost</span>:<span style="color: #f4a261;">4000</span>\r\<span style="color: #86abdc;">nConnection: </span><span style="color: #dfdfe0;">keep</span><span style="color: #aeafb0;">-</span><span style="color: #86abdc;">alive</span>\r\<span style="color: #86abdc;">nPragma: </span><span style="color: #dfdfe0;">no</span><span style="color: #aeafb0;">-</span><span style="color: #86abdc;">cache</span>\r\<span style="color: #86abdc;">nCache</span><span style="color: #aeafb0;">-</span><span style="color: #7ad5d6;">Control</span>: no<span style="color: #aeafb0;">-</span><span style="color: #86abdc;">cache</span>\r\<span style="color: #dfdfe0;">nSec</span><span style="color: #aeafb0;">-</span><span style="color: #7ad5d6;">Fetch</span><span style="color: #aeafb0;">-</span><span style="color: #7ad5d6;">Mode</span>: no<span style="color: #aeafb0;">-</span><span style="color: #86abdc;">cors</span>\r\<span style="color: #86abdc;">nDNT: </span><span style="color: #f4a261;">1</span>\r\<span style="color: #86abdc;">nUser</span><span style="color: #aeafb0;">-</span><span style="color: #7ad5d6;">Agent</span>: Mozilla<span style="color: #aeafb0;">/</span><span style="color: #f4a261;">5.0</span> <span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">Macintosh</span><span style="color: #aeafb0;">;</span> <span style="color: #7ad5d6;">Intel</span> Mac OS X <span style="color: #f4a261;">10_13_6</span><span style="color: #aeafb0;">)</span> AppleWebKit<span style="color: #aeafb0;">/</span><span style="color: #f4a261;">537.36</span> <span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">KHTML</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">like</span> <span style="color: #7ad5d6;">Gecko</span><span style="color: #aeafb0;">)</span> Chrome<span style="color: #aeafb0;">/</span><span style="color: #f4a261;">76.0</span><span style="color: #aeafb0;">.</span><span style="color: #f4a261;">3809.132</span> Safari<span style="color: #aeafb0;">/</span><span style="color: #f4a261;">537.36</span>\r\<span style="color: #86abdc;">nAccept: </span><span style="color: #dfdfe0;">image</span><span style="color: #aeafb0;">/</span><span style="color: #dfdfe0;">webp</span><span style="color: #aeafb0;">,</span><span style="color: #dfdfe0;">image</span><span style="color: #aeafb0;">/</span><span style="color: #dfdfe0;">apng</span><span style="color: #aeafb0;">,</span><span style="color: #dfdfe0;">image</span>/<span style="color: #aeafb0;">*</span><span style="color: #aeafb0;">,</span><span style="color: #aeafb0;">*</span>/*<span style="color: #aeafb0;">;</span><span style="color: #dfdfe0;">q</span><span style="color: #aeafb0;">=</span><span style="color: #f4a261;">0.8</span>\r\<span style="color: #dfdfe0;">nSec</span><span style="color: #aeafb0;">-</span><span style="color: #7ad5d6;">Fetch</span><span style="color: #aeafb0;">-</span><span style="color: #7ad5d6;">Site</span>: same<span style="color: #aeafb0;">-</span><span style="color: #86abdc;">origin</span>\r\<span style="color: #86abdc;">nReferer: </span><span style="color: #86abdc;">http</span><span style="color: #86abdc;">://</span><span style="color: #86abdc;">localhost</span>:<span style="color: #f4a261;">4000</span><span style="color: #aeafb0;">/</span>\r\<span style="color: #86abdc;">nAccept</span><span style="color: #aeafb0;">-</span><span style="color: #7ad5d6;">Encoding</span>: gzip<span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">deflate</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">br</span>\r\<span style="color: #86abdc;">nAccept</span><span style="color: #aeafb0;">-</span><span style="color: #7ad5d6;">Language</span>: pt<span style="color: #aeafb0;">-</span><span style="color: #7ad5d6;">PT</span><span style="color: #aeafb0;">,</span><span style="color: #dfdfe0;">pt</span><span style="color: #aeafb0;">;</span><span style="color: #dfdfe0;">q</span><span style="color: #aeafb0;">=</span><span style="color: #f4a261;">0.9</span><span style="color: #aeafb0;">,</span><span style="color: #dfdfe0;">en</span><span style="color: #aeafb0;">-</span><span style="color: #7ad5d6;">US</span><span style="color: #aeafb0;">;</span><span style="color: #dfdfe0;">q</span><span style="color: #aeafb0;">=</span><span style="color: #f4a261;">0.8</span><span style="color: #aeafb0;">,</span>en<span style="color: #aeafb0;">;</span><span style="color: #dfdfe0;">q</span><span style="color: #aeafb0;">=</span><span style="color: #f4a261;">0.7</span>\r\n\r\n
</div></code></pre>
<p>There's a whole bunch of documents detailing exactly how an HTTP request (on the various versions of the protocol) must be constructed, what it can contain, how those things are encoded and the same for the HTTP responses. We'll not read the RFC for the HTTP Protocol but basically implement the logic for parsing these requests and deliver a response on a more lightway approach.</p>
<p>We can see that the request is basically:</p>
<p>VERB <code>whitespace</code> PATH <code>whitespace</code> PROTOCOL/VERSION\r\nHEADERS\r\n\r\n</p>
<p>where <code>\r\n</code> is the carriage return escape sequence.</p>
<p>After the headers there would be a body but in this case since it's a get request there's none. In case of having a body the request should include a Content-Length header stating the size of the body although it's not totally required that it has.</p>
<p>So if we approach this from the point of view of creating a pipeline, basically we would need to:</p>
<ul>
<li>Parse the Verb</li>
<li>Parse the Path</li>
<li>Parse the Protocol</li>
<li>Parse the headers</li>
<li>Maybe Parse the Body if it has one</li>
<li>Dispatch to the appropriate route</li>
</ul>
<p>On each step we can then store the information we parsed so that we can later decide how to respond to it, which we'll do by dispatching that request into an appropriate handler.</p>
<p>We should read the RFC to make sure our server is completely correct, but like we said before, this is a lightweight version so we'll just read the basics from that request to decide what we need.</p>
<p>Verb, Path and Protocol are each one separated by a white space. Headers are separated from the previous section and between them by <code>\r\n</code>, meaning carriage return, a set of two characters, <code>\r</code> return and <code>\n</code> newline, each header key ends with <code>:</code> followed by a white space, after which comes the respective value.</p>
<p>The end of the headers is separated by double carriage return, <code>\r\n\r\n</code>. After this is the body and this can be formatted in different ways depending on the type of request.</p>
<p>There's many ways we can implement the parsing part, but we want it to be modular, so that anybody can hook their own things into a pipeline if they want, or change it completely, the idea is the basic pipeline will parse everything needed and then dispatch the request. We will want to implement some control on maximum length of the requests (or allow that even if by default it accepts anything). We want the pipeline to be halt-able, meaning that we can trigger an halt between any actions. We don't want to have explicit hardcoded behaviour, we want each step to be a call to a function that can be customised.</p>
<p>We will also want to have different kinds of actions, we'll want to have parsing/reading actions, that get part of the data from the socket and do something with it (parse it and if needed store it in the context of that specific request), we want to have actions that simply change the form of the data according to something in a certain place when they occur in the pipeline and we want actions that check the current state of what we have parsed/stored to decide if to continue parsing, halt, error, or dispatch.</p>
<p>One problem we will always run into is that the HTTP protocol doesn't require a request to say how many bytes it is in total, so we can't know how many bytes to read from the socket until we figure the end of the request. To add to that, we have the fact that we might read incomplete requests due to the buffering on the socket at the os level (and subsequent transmission to the Erlang VM). Most of the times the socket when read will contain all the data, but on big length requests we might need to read more than once from it.</p>
<p>When we set the socket to <code>&lbrace;:active, false&rbrace;</code> we explicitly told that we will somehow read the socket by ourselves. The reason to do this is because if we say <code>&lbrace;:active, true&rbrace;</code> we forego any possibility of applying backpressure to the data being sent and read from the socket, and someone could potentially flood our server with gigantic requests, possibly crashing it down in the process.</p>
<p>By saying <code>&lbrace;:active, false&rbrace;</code> the BEAM will not automatically send that data, it will be in the socket buffer, waiting to be read at which point we need to manually request a reading on it. One normal way of doing it is after we set the acceptor and pass the controlling process to the one that will receive the request, to set the socket to <code>&lbrace;:active, :once&rbrace;</code>, which means it will process once the data currently in the buffer (emptying it so at the os level the client tcp connection can push more data into it), send it as a message to the controlling process, and then switch automatically to <code>&lbrace;:active, false&rbrace;</code> again.</p>
<p>This has the benefit of allowing us to apply backpressure, it's like opening a faucet once for a little while and immediately closing it again. If we need to read more we repeat the same.</p>
<p>Other option is by using <code>:gen_tcp.recv</code>. In this way you can control how many bytes to read along with a timeout for it and instead of receiving that data as a message, you get the result of the read as the return of the function with <code>&lbrace;:ok, data&rbrace;</code>, or an <code>&lbrace;:error, reason&rbrace;</code> if there was some error (the socket was closed on the client for instance), or <code>:timeout</code> if the amount of bytes specified couldn't be read in that given time frame. <code>:gen_tcp.recv/3</code> takes the accepted socket from where to read as its first argument, the number of bytes to read as its second argument and the timeout as its third argument.</p>
<p>One thing to notice is that, if we specify a number that is not zero, then this function will only return after having read EXACTLY that number of bytes. In this case, this is not very useful, because we don't know beforehand how many bytes there will be in total, so unless we read a single byte at a time we would always end up timing out. Reading one byte at a time is not efficient in any way either. But if we specify the number as zero (0) then <code>recv</code> will act like <code>&lbrace;:active, :once&rbrace;</code>, in that it reads the whole available buffer in one go, and then returns that data. If we need to read more we call again <code>recv</code> and again we get whatever is in the buffer up to that point and so on. This again allows us to manually control the backpressure and the flow of data (we can even when creating the socket say what's the size we want for our buffer and other things but we'll not cover that).</p>
<p>(sidenote: you might ask then why is there an option to specify the number of bytes and not only 0, and the reason is, if you control the client (it's an application you wrote) or you have a defined protocol where you can specify the length, then you can optimise the readout to your specific system, network and even the client application flow. Of course when dealing with HTTP requests, that's not the case)</p>
<p>We can then implement a way of limiting the maximum number of bytes a request might have before we close the connection. We'll see that in more detail when we get to it. Now lets start implementing our basic request parser.</p>
<p>First we'll need to define a structure that will hold the parsed information in an organised way, so that we can check it. We also need to define a structure to hold the <code>configuration</code> information.</p>
<p>For the request lets create another module in the satellite app, <code>apps/satellite/lib/satellite_request.ex</code> . Open the file and add to it:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Satellite.Request</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3">  <span style="color: #9d79d6;">defstruct</span> <span style="color: #aeafb0;">[</span>
</div><div class="line" data-line="4">    <span style="color: #86abdc;">:verb</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="5">    <span style="color: #86abdc;">:protocol</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="6">    <span style="color: #86abdc;">:version</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="7">    <span style="color: #86abdc;">:accept</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="8">    <span style="color: #86abdc;">:body</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="9">    <span style="color: #86abdc;">path: </span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="10">    <span style="color: #86abdc;">host: </span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="11">    <span style="color: #86abdc;">query: </span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="12">    <span style="color: #86abdc;">headers: </span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="13">    <span style="color: #86abdc;">finished_headers: </span><span style="color: #f4a261;">false</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="14">    <span style="color: #86abdc;">halt: </span><span style="color: #f4a261;">false</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="15">    <span style="color: #86abdc;">params: </span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span>    
</div><div class="line" data-line="16"> <span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="17">  
</div><div class="line" data-line="18"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>The <code>:query</code>, <code>:headers</code> and <code>:params</code> field are maps, because they're key-value elements. <code>:path</code>  and <code>:host</code> are defined as lists although the url requested and the host will be strings if we want to dispatch on certain paths, match parts of the path, etc, and the same for the host/domain/port, we will need to decompose it into individual elements in order to do so. The remaining keys will either be booleans or strings/atoms that we will fill as we move through the pipeline.</p>
<p>Save that file.</p>
<p>Now let's create one for the configuration. The previous request structure is only used by the acceptors gen_statem and possibly any lib that depends on our whole application. On the other hand the config is used by the <code>launchpad</code> and <code>satellite</code>. So we will create a new app/lib to store these shared elements. We haven't added any dependencies to our apps until now but we will afterwards.</p>
<p>Go to the <code>apps</code> folder on the terminal again, and execute <code>mix new satellite_shared</code>.</p>
<p>Now create and open a file at <code>apps/satellite_shared/lib/satellite_configuration.ex</code></p>
<p>Place inside it the following:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Satellite.Configuration</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3">  <span style="color: #9d79d6;">defstruct</span> <span style="color: #aeafb0;">[</span>
</div><div class="line" data-line="4">    <span style="color: #86abdc;">:pipeline</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="5">    <span style="color: #86abdc;">:name</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="6">    <span style="color: #86abdc;">:router</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="7">    <span style="color: #86abdc;">port: </span><span style="color: #f4a261;">4000</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="8">    <span style="color: #86abdc;">acceptors: </span><span style="color: #f4a261;">5</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="9">    <span style="color: #86abdc;">max_size: </span><span style="color: #f4a261;">50_000</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="10">    <span style="color: #86abdc;">keep_full_request: </span><span style="color: #f4a261;">false</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="11">   
</div><div class="line" data-line="12"> <span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="13">
</div><div class="line" data-line="14"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Now open <code>apps/launchpad/mix.exs</code> and replace the <code>deps</code> function by:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defp</span> <span style="color: #dfdfe0;">deps</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">    <span style="color: #aeafb0;">[</span>
</div><div class="line" data-line="3">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:satellite</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">in_umbrella: </span><span style="color: #f4a261;">true</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="4">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:satellite_shared</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">in_umbrella: </span><span style="color: #f4a261;">true</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="5">    <span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="6"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Open the <code>apps/satellite/mix.exs</code> and replace the <code>deps</code> function by:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defp</span> <span style="color: #dfdfe0;">deps</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">    <span style="color: #aeafb0;">[</span>
</div><div class="line" data-line="3">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:satellite_shared</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">in_umbrella: </span><span style="color: #f4a261;">true</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="4">    <span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="5"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>The reason we were able to run previously without specifying these dependencies is because <code>mix</code> will compile and load all applications and modules in the umbrella, but if we were to assemble a release, then the compilation would fail, because the dependencies weren't specified.</p>
<p>Basically we're now saying <code>launchpad</code> depends on both the app <code>satellite</code> and <code>satellite_shared</code> and the app <code>satellite</code> depends on <code>satellite_shared</code>.</p>
<p>Ok, so now let's think about how we want to actually have this working. (I've done the thinking for you but I'll pretend it's fresh).</p>
<p>I'll throw in that one neat way of having it defined is as a list of things, so that we can move through it as we go. Each element of this list should have the type of action it is, the name for that particular step, which function to call for doing the step and also, because we might get things in several receives, an accumulator specific for that step. So say we want to encode the step for parsing the verb out of the request, given the 4 elements we mentioned previously, it could look like this:</p>
<p><code>&lbrace;:read, :verb, &amp;Satellite.Verb.parse/3, &lt;&lt;&gt;&gt;&rbrace;</code></p>
<p>So the action would be of the type <code>:read</code>, the name of the step would be <code>:verb</code>, the function that would execute this step would be <code>Satellite.Verb.parse/3</code> and the accumulator would be an empty binary.</p>
<p>Let's start writing it, first create another file in the satellite lib, <code>apps/satellite/lib/satellite_defaults.ex</code> and write in it:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Satellite.Defaults</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">  
</div><div class="line" data-line="3">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">default_pipeline</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="4">    <span style="color: #aeafb0;">[</span>
</div><div class="line" data-line="5">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:read</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:verb</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #7ad5d6;">Satellite.Verb</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">/</span><span style="color: #aeafb0;">3</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="6">    <span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="7">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="8"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Save it. We'll add the others as we go. Now we need to create a module <code>Satellite.Verb</code>. So lets create another file <code>apps/satellite/lib/satellite_verb.ex</code> and put in it:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Satellite.Verb</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;GET&quot;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:done</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">ctx</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">verb: </span><span style="color: #86abdc;">:get</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="4">
</div><div class="line" data-line="5">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;POST&quot;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:done</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">ctx</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">verb: </span><span style="color: #86abdc;">:post</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:cont</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="8">
</div><div class="line" data-line="9">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?\s</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="10">
</div><div class="line" data-line="11">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">h</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">h</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="12">
</div><div class="line" data-line="13">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:error</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;Parsing Verb&quot;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="14">  
</div><div class="line" data-line="15"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Here the idea is very simple, we create a recursive function. First this function will be called the first time with <code>(ctx, the_request_binary_from_the_socket, &lt;&lt;&gt;&gt;)</code> because the initial accumulator is <code>&lt;&lt;&gt;&gt;</code> as set in our pipeline definition. So it won't match the first 4 functions, but will match the 5th, were we pluck 1 single character from it, add call again parse with the remaining of the packet, while adding that single character we removed to the accumulator.</p>
<p>It repeats this until the accumulator is <code>&lt;&lt;&quot;GET&quot;&gt;&gt;</code> or <code>&lt;&lt;&quot;POST&quot;&gt;&gt;</code>, at which point we consider it done because we have a matching verb (right now it will fail for any other verb). If there was a white-space somewhere, it would ignore it and move on to the next character, but because it will assemble GET or POST before that it's never called, anyway, I'm leaving it there just because.</p>
<p>Most parsing will be similar to this, but it will have its own peculiarities. This should work even if for instance we were reading 1byte at a time from the socket, because in that case, we would read the first, rendering an accumulator of <code>&lt;&lt;&quot;G&quot;&gt;&gt;</code>, and an remaining of <code>&lt;&lt;&gt;&gt;</code>, which would match the 3rd function and in that case return <code>&lbrace;:cont, ctx, acc&rbrace;</code>, which would trigger a new read from the socket and consequent parsing.</p>
<p>Now how do we make our satellite actually work with this? So one thing we can do is treat our state of the gen_statem as the current step in the pipeline. With pattern matching we can describe this very elegantly, because if the pipeline is a list, we can simply pluck the first element from it and store it as the current state, and every time it moves we pluck another one, until we have no more steps to do, at which point we know we've finished the pipeline and parsed the full request. The complete story is a bit different because of the specifics of http requests, but that's the overall idea, we'll adjust as we need while going through it. So now we need to change how the <code>launchpad</code> is started, so that it uses our recent <code>Satellite.Configuration</code> struct.</p>
<p>Add this to <code>apps/launchpad/lib/launchpad.ex</code></p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1">  <span style="color: #9d79d6;">alias</span> <span style="color: #7ad5d6;">Satellite.Configuration</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">as: </span><span style="color: #7ad5d6;">Config</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3">
</div><div class="line" data-line="4">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">set_defaults</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">config</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="5">    <span style="color: #86abdc;">maybe_set_name</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">config</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="6">    <span style="color: #aeafb0;">|&gt;</span> <span style="color: #86abdc;">maybe_set_port</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="7">    <span style="color: #aeafb0;">|&gt;</span> <span style="color: #86abdc;">maybe_set_pipeline</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="8">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="9">  
</div><div class="line" data-line="10">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">maybe_set_name</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">Config</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #dfdfe0;">name</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">config</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">maybe_set</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:name</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">name</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:local</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">__MODULE__</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">config</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="11">
</div><div class="line" data-line="12">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">maybe_set_port</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">Config</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">port: </span><span style="color: #dfdfe0;">port</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">config</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">maybe_set</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:port</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">port</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">4000</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">config</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="13">
</div><div class="line" data-line="14">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">maybe_set_pipeline</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">Config</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">pipeline: </span><span style="color: #dfdfe0;">pipeline</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">config</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="15">	<span style="color: #86abdc;">maybe_set</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:pipeline</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">pipeline</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Satellite.Defaults</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">default_pipeline</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">config</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="16">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="17">
</div><div class="line" data-line="18">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">maybe_set</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">default</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">config</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">config</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">default</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="19">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">maybe_set</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">config</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #dfdfe0;">config</span>
</div></code></pre>
<p>And change <code>start_link</code> and <code>init</code> to the following:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">start_link</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">Config</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">config</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">    <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #dfdfe0;">name</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">ok_config</span> <span style="color: #aeafb0;">=</span> <span style="color: #86abdc;">set_defaults</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">config</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="3">    
</div><div class="line" data-line="4">    <span style="color: #dbc074;">:gen_statem</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">start_link</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">name</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">__MODULE__</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">ok_config</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="5"><span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">init</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">port: </span><span style="color: #dfdfe0;">port</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">config</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="8">    <span style="color: #7ad5d6;">Process</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">flag</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:trap_exit</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">true</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="9">    
</div><div class="line" data-line="10">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">socket</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dbc074;">:gen_tcp</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">listen</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">port</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:binary</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:packet</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:raw</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:active</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">false</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:reuseaddr</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">true</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="11">
</div><div class="line" data-line="12">    <span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">%</span><span style="color: #f6b079;">__MODULE__</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">socket: </span><span style="color: #dfdfe0;">socket</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">config: </span><span style="color: #dfdfe0;">config</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="13">    
</div><div class="line" data-line="14">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:starting</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:create_listener</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="15"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>We created some helper functions to set defaults in case it isn't passed into and also changed the <code>start_link</code> and <code>init</code> to use that. If there's no <code>:name</code>, <code>:port</code> or <code>:pipeline</code> set in the config it will set them to some default. Because we're now matching explicitly on the <code>%Config&lbrace;&rbrace;</code> struct in <code>start_link/1</code>, if you pass anything else it will fail with an unmatched function call.</p>
<p>Now we need to change the <code>satellite.ex</code> file, to use the pipeline and create the <code>handle_event</code> functions that will coordinate that.</p>
<p>I'm going to past the full file as it should look and we go through the changes:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Satellite</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">behaviour </span><span style="color: #86abdc;">:gen_statem</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4">  <span style="color: #9d79d6;">alias</span> <span style="color: #7ad5d6;">Satellite.Request</span>
</div><div class="line" data-line="5">
</div><div class="line" data-line="6">  <span style="color: #9d79d6;">defstruct</span> <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:socket</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:config</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:conn</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">pipeline: </span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">request: </span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">Request</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="7">  
</div><div class="line" data-line="8">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #f4a261;">true</span>
</div><div class="line" data-line="9">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">callback_mode</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:handle_event_function</span>
</div><div class="line" data-line="10">  
</div><div class="line" data-line="11">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">start_link</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">socket</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">opts</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="12">    <span style="color: #dbc074;">:gen_statem</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">start_link</span><span style="color: #aeafb0;">(</span><span style="color: #f6b079;">__MODULE__</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">socket</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">opts</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="13">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="14">  
</div><div class="line" data-line="15">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #f4a261;">true</span>
</div><div class="line" data-line="16">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">init</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">socket</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">config</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="17">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:waiting</span><span style="color: #aeafb0;">,</span>  <span style="color: #7ad5d6;">%</span><span style="color: #f6b079;">__MODULE__</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">socket: </span><span style="color: #dfdfe0;">socket</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">config: </span><span style="color: #dfdfe0;">config</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:wait</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="18">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="19">
</div><div class="line" data-line="20">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #f4a261;">true</span>
</div><div class="line" data-line="21">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:wait</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:waiting</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">socket: </span><span style="color: #dfdfe0;">socket</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">config: </span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">pipeline: </span><span style="color: #dfdfe0;">pipeline</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="22">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dbc074;">:gen_tcp</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">accept</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">socket</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="23">    
</div><div class="line" data-line="24">    <span style="color: #dbc074;">:gen_tcp</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">controlling_process</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">self</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="25">
</div><div class="line" data-line="26">    <span style="color: #dfdfe0;">n_data</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">conn: </span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">pipeline: </span><span style="color: #dfdfe0;">pipeline</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">request: </span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">Request</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="27">
</div><div class="line" data-line="28">    <span style="color: #86abdc;">set_next_step</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">n_data</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="29"> <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="30">
</div><div class="line" data-line="31">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:read</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">conn: </span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="32">    <span style="color: #9d79d6;">case</span> <span style="color: #dbc074;">:gen_tcp</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">recv</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">0</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">1000</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="33">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">packet</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="34">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:keep_state_and_data</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:parse</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">packet</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="35">
</div><div class="line" data-line="36">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:error</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">reason</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="37">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:response</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">request: </span><span style="color: #81b29a;">&quot;Error: </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span> <span style="color: #dfdfe0;">reason</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:send_response</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="38">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="39">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="40">
</div><div class="line" data-line="41">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:parse</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">packet</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">name</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">fun</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="42">
</div><div class="line" data-line="43">    <span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">fun</span><span style="color: #aeafb0;">.</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">packet</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="44">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:cont</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_request</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_acc</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="45">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">name</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">fun</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_acc</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">n_request</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:read</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="46">
</div><div class="line" data-line="47">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:done</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_request</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">remaining</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="48">        <span style="color: #86abdc;">set_next_step</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">n_request</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">remaining</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="49">
</div><div class="line" data-line="50">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:error</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">reason</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="51">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:response</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">request: </span><span style="color: #81b29a;">&quot;</span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span> <span style="color: #dfdfe0;">reason</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:send_response</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="52">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="53">    
</div><div class="line" data-line="54">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="55">
</div><div class="line" data-line="56">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:send_response</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:response</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">conn: </span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="57">     
</div><div class="line" data-line="58">     <span style="color: #dbc074;">:gen_tcp</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">send</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">make_response</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="59">
</div><div class="line" data-line="60">     <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:keep_state</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:close</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="61">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="62">
</div><div class="line" data-line="63">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:close</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">conn: </span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="64">    <span style="color: #dbc074;">:gen_tcp</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">close</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="65">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:waiting</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">conn: </span><span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:wait</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="66">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="67">
</div><div class="line" data-line="68">
</div><div class="line" data-line="69">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">set_next_step</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">pipeline: </span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">h</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">remaining</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="70">
</div><div class="line" data-line="71">    <span style="color: #dfdfe0;">event</span> <span style="color: #aeafb0;">=</span> <span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">remaining</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="72">              <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #86abdc;">:read</span>
</div><div class="line" data-line="73">              <span style="color: #738091;">_</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:parse</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">remaining</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="74">            <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="75">
</div><div class="line" data-line="76">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">h</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">pipeline: </span><span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">event</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="77">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="78">
</div><div class="line" data-line="79">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">set_next_step</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">pipeline: </span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_remaining</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="80">
</div><div class="line" data-line="81">    <span style="color: #dfdfe0;">n_request</span> <span style="color: #aeafb0;">=</span> <span style="color: #81b29a;">&quot;</span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span> <span style="color: #dfdfe0;">request</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span>
</div><div class="line" data-line="82">    
</div><div class="line" data-line="83">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:response</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">n_request</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:send_response</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="84">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="85">
</div><div class="line" data-line="86">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">make_response</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="87">    <span style="color: #dfdfe0;">b</span> <span style="color: #aeafb0;">=</span> <span style="color: #dbc074;">:erlang</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">iolist_to_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="88">    <span style="color: #dbc074;">:io_lib</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">fwrite</span><span style="color: #aeafb0;">(</span>
</div><div class="line" data-line="89">      <span style="color: #81b29a;">&quot;HTTP/1.0 200 OK</span><span style="color: #e0c989; font-weight: bold;">\n</span><span style="color: #81b29a;">Content-Type: text/html</span><span style="color: #e0c989; font-weight: bold;">\n</span><span style="color: #81b29a;">Content-Length: ~p</span><span style="color: #e0c989; font-weight: bold;">\n</span><span style="color: #e0c989; font-weight: bold;">\n</span><span style="color: #81b29a;">~s&quot;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="90">       <span style="color: #aeafb0;">[</span><span style="color: #dbc074;">:erlang</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">size</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">b</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">b</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="91">    <span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="92">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="93"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>So first, we changed the <code>defstruct</code> to hold a <code>%Satellite.Request&lbrace;&rbrace;</code> (we aliased the module so we can write <code>%Request&lbrace;&rbrace;</code> instead) by default instead of an empty map.</p>
<p>Then the <code>init</code> is the same as before, but the <code>:wait</code> event while <code>:waiting</code> is different. Now, because we know we have the pipeline in the <code>%Config&lbrace;&rbrace;</code> structure, we take out that through pattern matching and then after having made a connection we create a new structure with the <code>:conn</code>, the <code>:pipeline</code> value and an empty <code>%Satellite.Request&lbrace;&rbrace;</code> as the <code>:request</code>, we then, instead of returning the statem tuple, call the <code>set_next_step</code> function, which takes a <code>Satellite</code> struct, and the bytes read from the socket as the 2nd argument. In this case, since we're just starting the pipeline we don't have any bytes, so we pass an empty binary <code>&lt;&lt;&gt;&gt;</code>.</p>
<p>This function then pattern matches on the <code>:pipeline</code> key and sees if we have at least one element there, and in case we do, it means we haven't finished the pipeline yet. In that matching function we also check the already read data we have available to parse and depending wether it's empty (<code>&lt;&lt;&gt;&gt;</code>) or not, we set the next event for the state machine. This event will either be <code>&lbrace;:parse, data&rbrace;</code> or <code>:read</code> in case we don't have any data to parse. First time this is called it will obviously be <code>:read</code> because we passed <code>&lt;&lt;&gt;&gt;</code>.</p>
<p>In case we have no other elements in the pipeline, instead, we know we have reached the end of the pipeline and as such should send a response back. This function will change of course, for now it just does an inspect on the current <code>request</code> struct so that it becomes a stringified version, and then sets the next event to <code>:send_response</code>.</p>
<p>On the first iteration though we have a pipeline element, we will have a single one, so the function match will look like this:</p>
<p><code>set_next_step(%&lbrace;pipeline: [h | t]&rbrace; = data, remaining)</code></p>
<p>Where <code>h</code> will be <code>&lbrace;:read, :verb, &amp;Satellite.Verb.parse/3, &lt;&lt;&gt;&gt;&rbrace;</code> and <code>t</code> will be <code>[]</code>.</p>
<p>Because remaining is <code>&lt;&lt;&gt;&gt;</code>, event will be <code>:read</code>.
So the final return from the <code>set_next_step</code> will be:</p>
<p><code>&lbrace;:next_state, &lbrace;:read, :verb, &amp;Satellite.Verb.parse/3, &lt;&lt;&gt;&gt;&rbrace;, %&lbrace;data | pipeline: []&rbrace;, [&lbrace;:next_event, :internal, :read&rbrace;]&rbrace;</code></p>
<p>This shows how cool is the <code>:handle_event_function</code> type of callbacks, due to that we can have complex states as this one, which allows us to describe in very clean steps what should happen when such states have to process new events.</p>
<p>This means that now, it will trigger the event <code>:read</code> that doesn't care about what state it's in, and just does what we were doing before by reading from the socket. When it reads then it sets the next event to be <code>&lbrace;:parse, data_that_was_read&rbrace;</code>, and now this will trigger the next event were we parse and - in this case - we do care about what state we're in because it contains the function we need to call to handle this step.</p>
<p>We had set the state to be <code>&lbrace;:read, :verb, &amp;Satellite.Verb.parse/3, &lt;&lt;&gt;&gt;&rbrace;</code>, which means the accumulator starts empty. We also used the <code>&amp;</code> notation to capture that function, because what we want is a reference to a given function so that we can then apply it. We do that by calling
<code>fun.(request, packet, acc)</code>. The first argument is the current <code>%Request</code> struct as it is, the second is what was read from the socket up till now, and the third is the accumulator, which starts empty.</p>
<p>This function should return one of 3 possible outcomes (we would write a proper behaviour for this but now we'll skip it):</p>
<ul>
<li><code>&lbrace;:cont, new_request_struct, new_acc&rbrace;</code></li>
</ul>
<p>this return means that that given function was unable to finish with the current data retrieved from the socket, so we should ask to read more from the socket, it replaces the state of the <code>gen_statem</code> by almost the same as it is currently, with exception of the <code>acc</code>, which gets replaced by the <code>new_acc</code> returned from the function. It also replaces the <code>:request</code> key in the gen_statem's data, in case the <code>new_request_struct</code> has changed. When we get this event, the next event will be <code>:read</code> and afterwards it will trigger this event again, with new data read from the socket. The <code>new_request_struct</code> might or may not have changed, but to simplify logic we just replace it.</p>
<ul>
<li><code>&lbrace;:done, new_request_struct, remaining&rbrace;</code></li>
</ul>
<p>this return means, the function was able to according to its logic finish all it had to do, so this step can be considered complete, lets move to the next one. It includes the <code>new_request_struct</code> and any bytes that weren't parsed. This calls <code>set_next_step</code> which will follow the logic we already discussed, placing the next step in the pipeline as the current. In this case we might or may not have any remaining bytes available, and <code>set_next_step</code> will decide accordingly what is the next event to trigger</p>
<ul>
<li><code>&lbrace;:error, reason&rbrace;</code>
this is self explanatory - right now it just translated whatever is the error reason into a string and jumps right to the <code>:send_response</code> event. We will further down change this and the <code>:send_response</code> steps as well</li>
</ul>
<p>We will also need to add proper error catching but everything at its time.</p>
<p>If we look at what we have right now, we should be able to see some response already containing our <code>%Satellite.Request&lbrace;&rbrace;</code> struct and the proper verb parsed and included in it. Lets recompile / restart the iex shell, and do now:</p>
<p><code> Launchpad.start_link(%Satellite.Configuration&lbrace;&rbrace;)</code></p>
<p>You should see again the familiar <code>&lbrace;:ok, pid...&rbrace;</code>
Now lets open up a browser and visit again <a href="http://localhost:4000">http://localhost:4000</a> - you should be greeted by:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">Satellite.Request</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">accept: </span><span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">finished_headers: </span><span style="color: #f4a261;">false</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">halt: </span><span style="color: #f4a261;">false</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">headers: </span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">host: </span><span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">params: </span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">path: </span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">protocol: </span><span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">query: </span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">verb: </span><span style="color: #86abdc;">:get</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">version: </span><span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">&rbrace;</span>
</div></code></pre>
<p>And as you can see, the <code>:verb</code> key is set to <code>:get</code>. Very nice very good, great success!</p>
<p>Let's go adding one by one the remaining parsing steps, open <code>apps/satellite/lib/satellite_defaults.ex</code> and replace it by:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Satellite.Defaults</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">  
</div><div class="line" data-line="3">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">default_pipeline</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="4">    <span style="color: #aeafb0;">[</span>
</div><div class="line" data-line="5">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:read</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:verb</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #7ad5d6;">Satellite.Verb</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">/</span><span style="color: #aeafb0;">3</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="6">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:read</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:path</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #7ad5d6;">Satellite.Path</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">/</span><span style="color: #aeafb0;">3</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #f4a261;">false</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="7">    <span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="8">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="9">  
</div><div class="line" data-line="10"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Now let's create the <code>Satellite.Path</code> module, in <code>apps/satellite/lib/satellite_path.ex</code>. This one is going to be more complex because we want to separate the path into it's individual constituents, so if someone would visit <code>http://localhost:4000/basic/path</code> our final path list would look like <code>[&quot;basic&quot;, &quot;path&quot;]</code> and because a path might include also query strings, in the form of <code>?key=value&amp;key2=value2</code> we need to do more work, and in case there is query string we need to place it on the <code>:query</code> key of the <code>%Request&lbrace;&rbrace;</code> struct.</p>
<p>The reason we want to do this will become clearer when we design the dispatching mechanism, but it will allow us to do some cool stuff with it.</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Satellite.Path</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:cont</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="4">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?\s</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #f4a261;">false</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="5">
</div><div class="line" data-line="6">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?\s</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #f4a261;">true</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">prior</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="7">    <span style="color: #dfdfe0;">n_acc</span> <span style="color: #aeafb0;">=</span> <span style="color: #86abdc;">maybe_add_prior</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">prior</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="8">    
</div><div class="line" data-line="9">    <span style="color: #dfdfe0;">n_ctx</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="10">      <span style="color: #dfdfe0;">ctx</span> <span style="color: #aeafb0;">|</span>
</div><div class="line" data-line="11">      <span style="color: #86abdc;">path: </span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reverse</span><span style="color: #aeafb0;">(</span>
</div><div class="line" data-line="12">        <span style="color: #7ad5d6;">List</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">flatten</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">n_acc</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="13">      <span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="14">    <span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="15">
</div><div class="line" data-line="16">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:done</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="17">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="18">
</div><div class="line" data-line="19">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">query: </span><span style="color: #dfdfe0;">q</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?\s</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:query</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:value</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">value</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="20">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:done</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">ctx</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">query: </span><span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">q</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">value</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="21">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="22">
</div><div class="line" data-line="23">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?\s</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:done</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="24">
</div><div class="line" data-line="25">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?=</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:query</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:key</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="26">    <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:query</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:value</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="27">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="28">
</div><div class="line" data-line="29">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">h</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:query</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:key</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="30">    <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:query</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:key</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">h</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="31">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="32">
</div><div class="line" data-line="33">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">query: </span><span style="color: #dfdfe0;">q</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?&amp;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:query</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:value</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">value</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="34">    <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">ctx</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">query: </span><span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">q</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">value</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:query</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:key</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="35">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="36">
</div><div class="line" data-line="37">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">h</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:query</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:value</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">value</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="38">    <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:query</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:value</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">value</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">h</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="39">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="40">
</div><div class="line" data-line="41">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?/</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">prior</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="42">    <span style="color: #dfdfe0;">n_acc</span> <span style="color: #aeafb0;">=</span> <span style="color: #86abdc;">maybe_add_prior</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">prior</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="43">    <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #f4a261;">true</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_acc</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="44">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="45">
</div><div class="line" data-line="46">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">??</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:true</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">prior</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="47">    <span style="color: #dfdfe0;">n_acc</span> <span style="color: #aeafb0;">=</span> <span style="color: #86abdc;">maybe_add_prior</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">prior</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="48">    <span style="color: #dfdfe0;">n_ctx</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="49">      <span style="color: #dfdfe0;">ctx</span> <span style="color: #aeafb0;">|</span>
</div><div class="line" data-line="50">      <span style="color: #86abdc;">path: </span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reverse</span><span style="color: #aeafb0;">(</span>
</div><div class="line" data-line="51">        <span style="color: #7ad5d6;">List</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">flatten</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">n_acc</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="52">      <span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="53">    <span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="54">
</div><div class="line" data-line="55">    <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">n_ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:query</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:key</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="56">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="57">
</div><div class="line" data-line="58">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">h</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">prior</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="59">    <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #f4a261;">true</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">prior</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">h</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="60">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="61">
</div><div class="line" data-line="62">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:error</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;Parsing path&quot;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="63">
</div><div class="line" data-line="64">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">maybe_add_prior</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #dfdfe0;">acc</span>
</div><div class="line" data-line="65">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">maybe_add_prior</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">prior</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">prior</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="66">  
</div><div class="line" data-line="67"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>We won't go through all the logic in this one, but suffice to say that, it will parse bytes until it reads a <code>&quot;/&quot;</code>, at that point it will look to see if it has accumulated anything, in case it has it puts that as one element of the paths list. It does that until it either finds a whitespace or a <code>?</code> character. If it finds a <code>?</code> character it means it's expecting query parameters, so it changes its own internal acc state to now match on first extracting the value of the key for that query parameter, and once finding an <code>=</code> sign, switching to finding the value for that. Once it does it places those under the <code>:query</code> key on the context map (that is the <code>%Satellite.Request&lbrace;&rbrace;</code> struct), and it does this until again, it finds a white space.</p>
<p>When it finds a white space it considers this step complete. Now you know why URI's can't contain white-spaces and instead use either <code>+</code> or <code>%20</code>, imagine having to deal with that ...</p>
<p>Now our implementation doesn't deal with everything, it's definitively not RFC compliant, anyway, it will work mostly fine for what we want, and you can extend it by yourself, how the remaining works is left as an exercise.</p>
<p>Let's quit the shell and restart it, then run again:</p>
<p><code>Launchpad.start_link(%Satellite.Configuration&lbrace;&rbrace;)</code></p>
<p>And this time visit <code>http://localhost:4000/some/path?query1=val1</code></p>
<p>You should see now:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">Satellite.Request</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">accept: </span><span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">finished_headers: </span><span style="color: #f4a261;">false</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">halt: </span><span style="color: #f4a261;">false</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">headers: </span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">host: </span><span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">params: </span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">path: </span><span style="color: #aeafb0;">[</span><span style="color: #81b29a;">&quot;some&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;path&quot;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">protocol: </span><span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">query: </span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #81b29a;">&quot;query1&quot;</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #81b29a;">&quot;val1&quot;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">verb: </span><span style="color: #86abdc;">:get</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">version: </span><span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">&rbrace;</span>
</div></code></pre>
<p>So even more success! It correctly parsed the path and separated it into each individual segment and also the query string!</p>
<p>Next is the <code>Satellite.Conn</code>, create the file at <code>apps/satellite/lib/satellite_conn.ex</code> and place inside it:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Satellite.Conn</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;HTTP/1.1&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">?\r</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">?\n</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:done</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">ctx</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">version: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #f4a261;">1</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">1</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="4">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;HTTP/1.0&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">?\r</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">?\n</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:done</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">ctx</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">version: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #f4a261;">1</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">0</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="5">
</div><div class="line" data-line="6">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:cont</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="7">
</div><div class="line" data-line="8">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?\s</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="9">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">h</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">h</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="10">
</div><div class="line" data-line="11">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:error</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;Parsing Conn&quot;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="12"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Again we're not dealing with everything possible here, but for now it will work.</p>
<p>Set the <code>satellite_defaults.ex</code> to:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Satellite.Defaults</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">  
</div><div class="line" data-line="3">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">default_pipeline</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="4">    <span style="color: #aeafb0;">[</span>
</div><div class="line" data-line="5">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:read</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:verb</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #7ad5d6;">Satellite.Verb</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">/</span><span style="color: #aeafb0;">3</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="6">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:read</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:path</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #7ad5d6;">Satellite.Path</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">/</span><span style="color: #aeafb0;">3</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #f4a261;">false</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="7">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:read</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:conn</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #7ad5d6;">Satellite.Conn</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">/</span><span style="color: #aeafb0;">3</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="8">    <span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="9">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="10"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>You can restart the shell, start again the <code>launchpad</code> and visiting localhost should now show you the version as well in the struct.</p>
<p>Now we'll move to the headers part, add the following line to the <code>default_pipeline()</code> (don't forget to add a comma on the previous last line)</p>
<p><code>&lbrace;:read, :headers, &amp;Satellite.Headers.parse/3, &lbrace;:header, &lt;&lt;&gt;&gt;&rbrace;&rbrace;</code></p>
<p>And let's create the <code>apps/satellite/lib/satellite_headers.ex</code> file, and place this on it:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Satellite.Headers</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3">  <span style="color: #9d79d6;">import</span> <span style="color: #7ad5d6;">Satellite.Shared</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">only: </span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">downcase: </span><span style="color: #f4a261;">1</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="4">
</div><div class="line" data-line="5">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:cont</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="6">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?:</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:header</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:value</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="7">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?\s</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:header</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:header</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="8">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?\s</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:value</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:value</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="9">
</div><div class="line" data-line="10">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">h</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:header</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="11">    <span style="color: #dfdfe0;">n_h</span> <span style="color: #aeafb0;">=</span> <span style="color: #86abdc;">downcase</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">h</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="12">    <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:header</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_h</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="13">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="14">
</div><div class="line" data-line="15">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?\r</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:header</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="16">    <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:in_termination</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?\r</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="17">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="18">
</div><div class="line" data-line="19">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?\n</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:in_termination</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?\r</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="20">    <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:in_termination</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?\r</span><span style="color: #aeafb0;">,</span><span style="color: #81b29a;">?\n</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="21">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="22">
</div><div class="line" data-line="23">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?\r</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:in_termination</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?\r</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">?\n</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="24">    <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:in_termination</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?\r</span><span style="color: #aeafb0;">,</span><span style="color: #81b29a;">?\n</span><span style="color: #aeafb0;">,</span><span style="color: #81b29a;">?\r</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="25">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="26">
</div><div class="line" data-line="27">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?\n</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:in_termination</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?\r</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">?\n</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">?\r</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="28">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:done</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">ctx</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">finished_headers: </span><span style="color: #f4a261;">true</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="29">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="30">
</div><div class="line" data-line="31">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">h</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:in_termination</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?\r</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">?\n</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="32">    <span style="color: #dfdfe0;">n_h</span> <span style="color: #aeafb0;">=</span> <span style="color: #86abdc;">downcase</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">h</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="33">    <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:header</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">n_h</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="34">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="35">
</div><div class="line" data-line="36">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">headers: </span><span style="color: #dfdfe0;">headers</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?\r</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:value</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="37">    <span style="color: #dfdfe0;">value</span> <span style="color: #aeafb0;">=</span> <span style="color: #86abdc;">translate_header_content</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="38">    <span style="color: #dfdfe0;">n_ctx</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">ctx</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">headers: </span><span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">headers</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">value</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="39">    <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">n_ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:in_termination</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?\r</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="40">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="41">
</div><div class="line" data-line="42">
</div><div class="line" data-line="43">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">h</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:value</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="44">
</div><div class="line" data-line="45">    <span style="color: #dfdfe0;">n_h</span> <span style="color: #aeafb0;">=</span> <span style="color: #9d79d6;">case</span> <span style="color: #86abdc;">downcased_header?</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="46">            <span style="color: #f4a261;">true</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #86abdc;">downcase</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">h</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="47">            <span style="color: #738091;">_</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #dfdfe0;">h</span>
</div><div class="line" data-line="48">          <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="49">    
</div><div class="line" data-line="50">    <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:value</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_h</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="51">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="52">
</div><div class="line" data-line="53">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:error</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;Parsing headers&quot;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="54">
</div><div class="line" data-line="55">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">translate_header_content</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;content-length&quot;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">val</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">val</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="56">    <span style="color: #dbc074;">:erlang</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">binary_to_integer</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">val</span><span style="color: #aeafb0;">)</span>  
</div><div class="line" data-line="57">    <span style="color: #9d79d6;">catch</span> <span style="color: #738091;">_</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #f4a261;">0</span>
</div><div class="line" data-line="58">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="59">
</div><div class="line" data-line="60">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">translate_header_content</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">val</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #dfdfe0;">val</span>
</div><div class="line" data-line="61">
</div><div class="line" data-line="62">
</div><div class="line" data-line="63">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">downcased_header?</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;content-type&quot;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #f4a261;">true</span>
</div><div class="line" data-line="64">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">downcased_header?</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;accept&quot;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #f4a261;">true</span>
</div><div class="line" data-line="65">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">downcased_header?</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #f4a261;">false</span>
</div><div class="line" data-line="66"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Before doing some explanations, lets create/rewrite the <code>apps/satellite_shared/lib/satellite_shared.ex</code> (it should be there unless you deleted it), and place this inside of it:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Satellite.Shared</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3">  <span style="color: #9d79d6;">use</span> <span style="color: #7ad5d6;">Bitwise</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">only_operators: </span><span style="color: #f4a261;">true</span>
</div><div class="line" data-line="4">  
</div><div class="line" data-line="5">  <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">each</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">?A</span><span style="color: #aeafb0;">..</span><span style="color: #81b29a;">?Z</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">value</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="6">    <span style="color: #dfdfe0;">downcased</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">value</span> <span style="color: #aeafb0;">^^^</span> <span style="color: #f4a261;">32</span>
</div><div class="line" data-line="7">    <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">downcase</span><span style="color: #aeafb0;">(</span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">value</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">downcased</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="8">  <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="9">
</div><div class="line" data-line="10">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">downcase</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">val</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #dfdfe0;">val</span>
</div><div class="line" data-line="11"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>So this module uses the <code>Bitwise</code> macros, we specify we only want the <code>operators</code> type, which are in the form of <code>^^^</code> (which is the same as using the <code>Bitwise.bxor(a, b)</code>).</p>
<p>We use some simple macro magic to basically, at compile time, create a list of functions for all letters that can be uppercase that just return their downcased counterpart. We have then a catch all that just returns the arg passed into it as it is, because if it's being called the reason is the arg isn't an uppercased letter.</p>
<p>In erlang strings are lists of integers that are represented by their ascii code, so for instance <code>'A'</code> is actually a list with one element, the integer <code>65</code>, as in <code>[65]</code>. When erlang sees a list that is composed only of printable ascii characters it actually prints them in the shell as characters! So if you write on the shell <code>[65, 66, 67]</code>, you'll see <code>'ABC'</code>.</p>
<p>The elixir operator prefix <code>?</code> before a character actually gives us the numeric code for that character. If you do <code>?A</code> you'll see <code>65</code>. So if you use a range such as <code>?A..?Z</code> what will happen is that the range will be <code>65..90</code>, which encompasses all the regular uppercase letters in the alphabet.</p>
<p>The ascii table design also has a very neat property when it comes to the alphabet letters, they're placed in such a way, that if you flip one single bit in them they become the other case, and that's what <code>value ^^^ 32</code> does, so if <code>?A</code> is 65, when you do that bitwise operation of <code>bxor 32</code> on it it becomes 97, which is the ascii code for <code>a</code> so effectively you downcased the character.</p>
<p>Knowing this we can see that basically we define all these functions with those 5 lines of code.</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">downcase</span><span style="color: #aeafb0;">(</span><span style="color: #f4a261;">65</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #f4a261;">97</span>
</div><div class="line" data-line="2"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">downcase</span><span style="color: #aeafb0;">(</span><span style="color: #f4a261;">66</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #f4a261;">98</span>
</div><div class="line" data-line="3"><span style="color: #86abdc;">...</span> <span style="color: #86abdc;">all</span> <span style="color: #86abdc;">other</span> <span style="color: #dfdfe0;">integers</span> <span style="color: #aeafb0;">in</span> <span style="color: #86abdc;">the</span> <span style="color: #dfdfe0;">range</span>
</div><div class="line" data-line="4"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">downcase</span><span style="color: #aeafb0;">(</span><span style="color: #f4a261;">90</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #f4a261;">122</span>
</div><div class="line" data-line="5"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">downcase</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">something_else</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #dfdfe0;">something_else</span>
</div></code></pre>
<p>And there's it! A downcase function very succintly written that doesn't do any string work, assembled at compile time. Now, this only works with ascii letters, but that's fine, because that's what we need when parsing a request at this level. We would need to add other properties for when possibly parsing url encoded characters that aren't ascii, but that is left as an exercise.</p>
<p>You can now also see why we used <code>&lt;&lt;?some_character, ....&gt;&gt;</code> in the pattern matching, basically it gives us the numeric code of the character and because binaries are at their inner structure integer sequences it works.</p>
<p>The headers <code>parse</code> function on the other hand is again following the same logic as the previous ones, it starts with an accumulator of <code>&lbrace;:header, &lt;&lt;&gt;&gt;&rbrace;</code>, and adds characters to the <code>&lt;&lt;&gt;&gt;</code> until it runs into a <code>:</code>, which signifies that the key for the header is finished, and then switches the accumulator to <code>&lbrace;:value, previously_parsed_header, &lt;&lt;&gt;&gt;&rbrace;</code> which now accumulates characters until it runs into <code>\r</code> which will be the ending sequence, so we change the acc to be <code>:in_termination</code> mode, when followed by <code>\n</code> indicates the header and its value has finished, if it's followed by another <code>\r\n</code> sequence then it means all headers have been parsed, if it's not we know we're in another header key and we change to start accumulating the new header key and then value and then entering again the termination sequence until we hit <code>\r\n\r\n</code>, and we're now done with the request unless it has a body too, which it won't in a <code>get</code> request.</p>
<p>The headers keys should be case insensitive, so we always downcase them. We also add some logic for certain headers that we want their values to also be always downcased, namely <code>content-type</code> and <code>accept</code>. We could add additional ones or remove these if we wanted to. We also add a special case for the <code>content-length</code> header in case it's present, before we set it in the request struct, we try to translate it into an integer value because that will be more useful if we wanted then to use the value to count how many bytes we need to parse or whatever.</p>
<p>If you restart the iex console and the launchpad, and then visit localhost you should see that now we also have the <code>headers</code> key filled with all headers neatly mapped.</p>
<p>The same way we downcase the value for certain headers, we could also create, if wanted, a special white-list of header keys to be placed as :atoms in our headers map, but that would be confusing by mixing both atom and string keys so we won't worry with that now.</p>
<p>Let's add this new pipeline element to <code>apps/satellite/lib/satellite_defaults.ex</code></p>
<p><code>&lbrace;:noread, :host, &amp;Satellite.Host.set/2, nil&rbrace;</code></p>
<p>And create the respective module in <code>apps/satellite/lib/satellite_host.ex</code> with the following content:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Satellite.Host</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3">  <span style="color: #9d79d6;">import</span> <span style="color: #7ad5d6;">Satellite.Shared</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">only: </span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">downcase: </span><span style="color: #f4a261;">1</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="4">
</div><div class="line" data-line="5">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">set</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">headers: </span><span style="color: #dfdfe0;">headers</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="6">    <span style="color: #dfdfe0;">host</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">get</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">headers</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;host&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;&quot;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="7">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">ctx</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">host: </span><span style="color: #86abdc;">split_host</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">host</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="8">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="9">
</div><div class="line" data-line="10">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">split_host</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">val</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">split_host</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">val</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="11">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">split_host</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">segment</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reverse</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">segment</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="12">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">split_host</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?.</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">segment</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">split_host</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">segment</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="13">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">split_host</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?:</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">segment</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reverse</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">segment</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="14">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">split_host</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">h</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">segment</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="15">    <span style="color: #dfdfe0;">n_h</span> <span style="color: #aeafb0;">=</span> <span style="color: #86abdc;">downcase</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">h</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="16">    <span style="color: #86abdc;">split_host</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">segment</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_h</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="17">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="18">
</div><div class="line" data-line="19">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">split_host</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="20"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>This step in the pipeline is new, so we also have to implement our handle_event for this particular case.</p>
<p>Place this <code>handle_event</code> function between the existing <code>...:internal, :wait</code> and <code>...:internal, :read</code>, the order in which these appear is important, because otherwise, if this was after the <code>:internal, :read</code> that would be the one being matched and it would hang and timeout waiting for new data on the socket, since it doesn't care about which state we're in. By placing this one before, we actually make it so that when the state is of type <code>&lbrace;:noread, ....&rbrace;</code> it will be called instead of anything else.</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">event</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:noread</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_name</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">fun</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">    <span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">fun</span><span style="color: #aeafb0;">.</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="3">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_request</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="4">        <span style="color: #86abdc;">set_next_step</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">n_request</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:event</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">event</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="5">
</div><div class="line" data-line="6">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:error</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">reason</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="7">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:response</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">request: </span><span style="color: #81b29a;">&quot;Error: </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span> <span style="color: #dfdfe0;">reason</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:send_response</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="8">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="9"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Now, the <code>event</code> that is matched as the second argument already contains either <code>&lbrace;:parse, data&rbrace;</code> or <code>:read</code> as its event, so we will pass the remaining to <code>set_next_step</code> as a new type of tuple, <code>&lbrace;:event, event&rbrace;</code> and change our <code>set_next_step</code> function to account for this new type by changing it to:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">set_next_step</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">pipeline: </span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">h</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">remaining</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3">    <span style="color: #dfdfe0;">event</span> <span style="color: #aeafb0;">=</span> <span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">remaining</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="4">              <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #86abdc;">:read</span>
</div><div class="line" data-line="5">              <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:event</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">event</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #dfdfe0;">event</span>
</div><div class="line" data-line="6">              <span style="color: #738091;">_</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:parse</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">remaining</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="7">            <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="8">
</div><div class="line" data-line="9">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">h</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">pipeline: </span><span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">event</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="10"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>This way, it sets the already existing defined event as the next one.
Let's restart iex and launchpad and make sure its still working, we should now see the host key populated as well. Again, we're setting it as a list, instead of a plain string, because, imagine we would want to distinguish between requests in our router that went to a certain subdomain, by having it as a list split by the periods, we will be able to easily encode that logic in our dispatcher/router, which is not evident when you only see a list with a single element <code>[&quot;localhost&quot;]</code>, but if it was <code>[&quot;mysubdomain&quot;, &quot;domain&quot;, &quot;com&quot;]</code> things change, the same if we wanted to have localised logic pertaining to the top domain, then it becomes more evident why it's a good idea.</p>
<p>Next on the pipeline will be this:</p>
<p><code>&lbrace;:noread, :accept, &amp;Satellite.Accept.set/2, nil&rbrace;</code></p>
<p>Since we already wrote the handle for the <code>:noread</code> case we just need to write a module at <code>apps/satellite/lib/satellite_accept.ex</code> with:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Satellite.Accept</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">extract</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">headers: </span><span style="color: #dfdfe0;">headers</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="4">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">ctx</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">accept: </span><span style="color: #86abdc;">extract_accept</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">headers</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="5">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">extract_accept</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #81b29a;">&quot;accept&quot;</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;application/json&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:json</span>
</div><div class="line" data-line="8">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">extract_accept</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #81b29a;">&quot;accept&quot;</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;text/html&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:html</span>
</div><div class="line" data-line="9">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">extract_accept</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:any</span>
</div><div class="line" data-line="10">    
</div><div class="line" data-line="11"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Now this is very basic, perhaps we would like to do as we did with paths and hosts to split all accepted content-types and create a list of that that we could further match down the road but for now this will do, if the first characters of the header are <code>application/json</code> or <code>text/html</code> we set it to <code>:json</code> or <code>:html</code> respectively, anything else we set to <code>:any</code> (which is obviously incorrect, but we would also need to set up mimes and... we'll leave it for a future occasion).</p>
<p>Restart iex and the launchpad, you should now see the <code>accept</code> key also populated.</p>
<p>We're getting closer to finishing our first version of our server. Add this new step to the pipeline:</p>
<p><code>&lbrace;:check, :check_request_type, &amp;Satellite.Check.check/2, nil&rbrace;</code></p>
<p>And create <code>apps/satellite/lib/satellite_check.ex</code> with:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Satellite.Check</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">check</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">verb: </span><span style="color: #86abdc;">:get</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:dispatch</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="4">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">check</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">verb: </span><span style="color: #86abdc;">:post</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="5">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">check</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:dispatch</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="6"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>This of course is not enough to cover everything an http request might have, but is enough for our sample, if it's a <code>get</code> request we'll immediately run the not yet written <code>dispatch</code> event and if it's a <code>post</code> we will actually want to continue parsing. Now we need to write the corresponding handling for this event with those possible return values on our <code>satellite.ex</code> gen_statem:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">event</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:check</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_name</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">fun</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">    <span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">fun</span><span style="color: #aeafb0;">.</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="3">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_request</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="4">        <span style="color: #86abdc;">set_next_step</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">n_request</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:event</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">event</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="5">
</div><div class="line" data-line="6">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:dispatch</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_request</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="7">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:dispatching</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">n_request</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:dispatch</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="8">
</div><div class="line" data-line="9">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:response</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">resp</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="10">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:response</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">resp</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:send_response</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="11">
</div><div class="line" data-line="12">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:error</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">reason</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="13">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:response</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">request: </span><span style="color: #81b29a;">&quot;Error, </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span> <span style="color: #dfdfe0;">reason</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:send_response</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="14">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="15"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Again this needs to be placed before the <code>handle_event(:internal, :read.....)</code> function. There's some things we haven't implemented yet, like the <code>:dispatch</code> event and in the <code>&lbrace;:error, ...&rbrace;</code> or <code>&lbrace;:response, ...&rbrace;</code> we're just doing a very silly thing, so to correct that we will now work on the router and afterwards implement the request dispatcher and lastly the body parsing step. If we restart the shell and <code>launchpad</code> we'll now hit an error when visiting the page because the next event <code>:dispatch</code> isn't implemented yet.</p>
<p>For the router we'll use some of elixir's macro magic. Macros have some complexity but also allow us to write some really useful code. We'll try to not abuse their usage and basically write code that is still readable, with the main difference being it's written to be run at compile time. I'm no expert in elixir macros, so I won't explain everything (there's much I don't understand also), but basically they allow you to define AST code to be used in code generation at compile time.</p>
<p>What we want to achieve is the ability to create a module and then be able to write:</p>
<p><code>route &quot;get&quot;, &quot;/some/:path&quot;, AnotherModule, :a_function</code></p>
<p>(just like Phoenix does for us, but our version will be very plain and lacking many other features)</p>
<p>And with this create a route that accepts a <code>get</code> request, on a path composed by <code>/some/*anything*</code> and calls a <code>:a_function</code> on <code>AnotherModule</code> passing it the parsed request, and in the process setting a variable in the params with key <code>:path</code> set to the whatever was the second segment of that path.</p>
<p>So we want to accept literal paths, path segments to be bound to a named key (prefixed by <code>:</code>), or any segment (<code>*</code>). We also want for each route to be able to accept optionally a host/domain to be matched, defaulting to <code>*</code> (any), and again offering the possibility of binding those parts of the domain to named keys in the params map that will be populated in the request. Create the file <code>apps/satellite/lib/satellite_routing.ex</code> and place in it:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Satellite.Routing</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3">
</div><div class="line" data-line="4">  <span style="color: #9d79d6;">defmacro</span> <span style="color: #86abdc;">__using__</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_opts</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="5">    <span style="color: #9d79d6;">quote</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="6">      <span style="color: #9d79d6;">import</span> <span style="color: #7ad5d6;">Satellite.Routing</span>
</div><div class="line" data-line="7">      <span style="color: #f6b079;">@</span><span style="color: #f6b079;">before_compile </span><span style="color: #7ad5d6;">Satellite.Routing</span>
</div><div class="line" data-line="8">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="9">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="10">
</div><div class="line" data-line="11">  <span style="color: #9d79d6;">defmacro</span> <span style="color: #86abdc;">route</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">verb</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">path</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">module</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">function</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">domain</span> <span style="color: #aeafb0;">\\</span> <span style="color: #81b29a;">&quot;*&quot;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="12">
</div><div class="line" data-line="13">    <span style="color: #dfdfe0;">verb_atom</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">String</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_atom</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">String</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">downcase</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">verb</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="14">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">path_splitted</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">vars</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #86abdc;">split_path</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">path</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="15">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">domain_splitted</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">domain_vars</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #86abdc;">split_domain</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">domain</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="16">    <span style="color: #dfdfe0;">all_vars</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">vars</span> <span style="color: #aeafb0;">++</span> <span style="color: #dfdfe0;">domain_vars</span>
</div><div class="line" data-line="17">    
</div><div class="line" data-line="18">    <span style="color: #9d79d6;">quote</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="19">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">route</span><span style="color: #aeafb0;">(</span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">verb_atom</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">path_splitted</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">domain_splitted</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">params: </span><span style="color: #dfdfe0;">params</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="20">        <span style="color: #dfdfe0;">ctx</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="21">          <span style="color: #dfdfe0;">request</span> <span style="color: #aeafb0;">|</span>
</div><div class="line" data-line="22">          <span style="color: #86abdc;">params: </span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">all_vars</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">params</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">var</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="23">            <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Macro</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">escape</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">var</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="24">          <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="25">        <span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="26">        
</div><div class="line" data-line="27">        <span style="color: #86abdc;">apply</span><span style="color: #aeafb0;">(</span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">module</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">function</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="28">      <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="29">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="30">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="31">
</div><div class="line" data-line="32">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">split_path</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">path</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="33">    <span style="color: #9d79d6;">case</span> <span style="color: #7ad5d6;">String</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">split</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">path</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;/&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">trim: </span><span style="color: #f4a261;">true</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="34">      <span style="color: #aeafb0;">[</span><span style="color: #81b29a;">&quot;*&quot;</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">(</span><span style="color: #9d79d6;">quote</span> <span style="color: #86abdc;">do: </span><span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="35">      
</div><div class="line" data-line="36">      <span style="color: #dfdfe0;">split</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="37">          <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">split</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span>
</div><div class="line" data-line="38">            <span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;*&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">acc1</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc2</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="39">              <span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">(</span><span style="color: #9d79d6;">quote</span> <span style="color: #86abdc;">do: </span><span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">acc1</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc2</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="40">            
</div><div class="line" data-line="41">            <span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?:</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">acc1</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc2</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="42">              <span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">Macro</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">var</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">String</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">acc1</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #7ad5d6;">String</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Macro</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">var</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">String</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">acc2</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="43">            
</div><div class="line" data-line="44">            <span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">other</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">acc1</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc2</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="45">              <span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">other</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">acc1</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc2</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="46">            
</div><div class="line" data-line="47">          <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="48">          <span style="color: #aeafb0;">|&gt;</span> <span style="color: #9d79d6;">case</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="49">               <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">paths</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">vars</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reverse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">paths</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reverse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">vars</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="50">             <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="51">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="52"> <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="53">
</div><div class="line" data-line="54">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">split_domain</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">domain</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="55">    <span style="color: #9d79d6;">case</span> <span style="color: #7ad5d6;">String</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">split</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">domain</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;.&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">trim: </span><span style="color: #f4a261;">true</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="56">      <span style="color: #aeafb0;">[</span><span style="color: #81b29a;">&quot;*&quot;</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">(</span><span style="color: #9d79d6;">quote</span> <span style="color: #86abdc;">do: </span><span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="57">      
</div><div class="line" data-line="58">      <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?:</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="59">          <span style="color: #dfdfe0;">host_var</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">String</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_atom</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;host_</span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #dfdfe0;">rem</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="60">          <span style="color: #aeafb0;">&lbrace;</span><span style="color: #7ad5d6;">Macro</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">var</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">host_var</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">host_var</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Macro</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">var</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">host_var</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="61">
</div><div class="line" data-line="62">        <span style="color: #dfdfe0;">split</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="63">        <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">split</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span>
</div><div class="line" data-line="64">          <span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;*&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">acc1</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc2</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="65">            <span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">(</span><span style="color: #9d79d6;">quote</span> <span style="color: #86abdc;">do: </span><span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">acc1</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc2</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="66">
</div><div class="line" data-line="67">          <span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?\\</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">acc1</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc2</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">rem</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">acc1</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc2</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="68">          
</div><div class="line" data-line="69">          <span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">?:</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">acc1</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc2</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="70">            <span style="color: #dfdfe0;">host_var</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">String</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_atom</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;host_</span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #dfdfe0;">rem</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="71">            <span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">Macro</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">var</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">host_var</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">acc1</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">host_var</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Macro</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">var</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">host_var</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">acc2</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="72">          
</div><div class="line" data-line="73">          <span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">other</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">acc1</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc2</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="74">            <span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">other</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">acc1</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc2</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="75">          
</div><div class="line" data-line="76">        <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="77">        <span style="color: #aeafb0;">|&gt;</span> <span style="color: #9d79d6;">case</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="78">             <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">paths</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">vars</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reverse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">paths</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reverse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">vars</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="79">           <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="80">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="81">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="82">
</div><div class="line" data-line="83">
</div><div class="line" data-line="84">  <span style="color: #9d79d6;">defmacro</span> <span style="color: #86abdc;">__before_compile__</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_env</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="85">    <span style="color: #9d79d6;">quote</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="86">      <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">route</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_ctx</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="87">        <span style="color: #7ad5d6;">Satellite.Response</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">not_found</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="88">      <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="89">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="90">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="91"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>We start by defining a <code>__using__</code> macro. This is a special macro definition that then allows us to write <code>use Name_of_the_module_where_the_using_is_defined</code> and it automatically makes the contents of block available in that module.</p>
<p>This <code>__using__</code> does only two things, it imports the module to where it is invoked and sets a hook to be run before that module that calls <code>use</code> is compiled.</p>
<p>Then we define our actual <code>route</code> macro. This macro accepts 4 or 5 arguments, defaulting the last one to <code>&quot;*&quot;</code> (the domain). It takes the verb to match, the path, the module to call, and the function in that module to call and, optionally a domain string to match.</p>
<p>With this info it makes some transformations, the verb to an atom (to match what our parser creates), splits the <code>path</code> into its own individual segments - it does this by a regular function, and with help of <code>Macro.var</code> creates representations for <code>variables</code> -</p>
<p>this is what allows us to actually transform a segment such as <code>:something</code>, into a variable in the function definition, and then use that and the parsed named to set a key in the params map with the value that that variable will be bound to when ran at runtime. Since this is creating a AST representation of code it doesn't have any values right now, it just has a &quot;representation&quot; of what that code will be when run -</p>
<p>and does the same for the domain. On the splitting functions, you can see that we treat the <code>&quot;*&quot;</code> match in the domain and path in a special way when it's the only segment. Because if we treated it as other segments, the generated code would look like <code>[ _ ]</code>. If then someone did a request and our host was <code>host.domain.com</code>, this would be split into <code>[&quot;host&quot;, &quot;domain&quot;, &quot;com&quot;]</code>, and that wouldn't match a list with a single value like <code>[ _ ]</code>, so we need to treat it specially so that the whole thing is simply <code>_</code>, this way it matches anything like the wildcard actually means, either <code>[&quot;localhost&quot;]</code>, or <code>[&quot;some&quot;, &quot;domain&quot;, &quot;com&quot;]</code>.</p>
<p>Then, because we do <code>quote do</code> and inside it define a function, when the macro is called from some other module, what will actually happen is that this function definition we're creating is written in that module with the arguments we prepared.</p>
<p>So let's say again we have this module:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Test.Router</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">    <span style="color: #9d79d6;">use</span> <span style="color: #7ad5d6;">Satellite.Routing</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4">    <span style="color: #86abdc;">route</span> <span style="color: #81b29a;">&quot;get&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;/some/:path&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">AnotherModule</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:a_function</span>
</div><div class="line" data-line="5"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>(the route macro could be written as <code>route(&quot;get&quot;, &quot;/some/:path&quot;, AnotherModule, :a_function)</code>, but we can omit parenthesis and in this case it makes it look more declarative, like the Phoenix Router).</p>
<p>When elixir compiles this particular module with that sample code, what actually ends up being defined is</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Test.Router</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">    <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">route</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:get</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #81b29a;">&quot;some&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">path</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">params: </span><span style="color: #dfdfe0;">params</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="3">        <span style="color: #dfdfe0;">ctx</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="4">            <span style="color: #dfdfe0;">request</span> <span style="color: #aeafb0;">|</span> 
</div><div class="line" data-line="5">            <span style="color: #86abdc;">params: </span> 
</div><div class="line" data-line="6">                <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:path</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">ast_representation_of_the_var_variable</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">params</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">var</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="7">                    <span style="color: #7ad5d6;">Map</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">put</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">key</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">var</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="8">                <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="9">            <span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="10">
</div><div class="line" data-line="11">        <span style="color: #86abdc;">apply</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">AnotherModule</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:a_function</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">ctx</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="12">	<span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="13">
</div><div class="line" data-line="14">    <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">route</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_ctx</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #7ad5d6;">Satellite.Response</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">not_found</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="15"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>The last <code>route</code> definition comes from the <code>@before_compile Satellite.Routing</code> declaration in the <code>__using__</code> macro, which basically allows us to run that macro function that defines that route, after the other macros have been run, but before compilation, so they end up having the correct order.</p>
<p>We can see how we can use this in our <code>satellite</code> gen_statem to dispatch the requests since we have the verb, the path and domain neatly decomposed into segments  from the parsing we do in the pipeline.</p>
<p>So now we need to change our <code>satellite.ex</code> file. The changes are mostly self-evident but to prevent errors I'm just going to past the full contents of the file as it should be:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Satellite</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">behaviour </span><span style="color: #86abdc;">:gen_statem</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4">  <span style="color: #9d79d6;">alias</span> <span style="color: #7ad5d6;">Satellite</span><span style="color: #aeafb0;">.</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #7ad5d6;">Request</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Response</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="5">  
</div><div class="line" data-line="6">  <span style="color: #9d79d6;">defstruct</span> <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:socket</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:config</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:conn</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:response</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:router</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">pipeline: </span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">request: </span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">Request</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="7">  
</div><div class="line" data-line="8">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #f4a261;">true</span>
</div><div class="line" data-line="9">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">callback_mode</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">:handle_event_function</span>
</div><div class="line" data-line="10">  
</div><div class="line" data-line="11">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">start_link</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">socket</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">opts</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="12">    <span style="color: #dbc074;">:gen_statem</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">start_link</span><span style="color: #aeafb0;">(</span><span style="color: #f6b079;">__MODULE__</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">socket</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">opts</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="13">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="14">  
</div><div class="line" data-line="15">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #f4a261;">true</span>
</div><div class="line" data-line="16">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">init</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">socket</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">config</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="17">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:waiting</span><span style="color: #aeafb0;">,</span>  <span style="color: #7ad5d6;">%</span><span style="color: #f6b079;">__MODULE__</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">socket: </span><span style="color: #dfdfe0;">socket</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">config: </span><span style="color: #dfdfe0;">config</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:wait</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="18">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="19">
</div><div class="line" data-line="20">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">impl </span><span style="color: #f4a261;">true</span>
</div><div class="line" data-line="21">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:wait</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:waiting</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">socket: </span><span style="color: #dfdfe0;">socket</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">config: </span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">router: </span><span style="color: #dfdfe0;">router</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">pipeline: </span><span style="color: #dfdfe0;">pipeline</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="22">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dbc074;">:gen_tcp</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">accept</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">socket</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="23">    
</div><div class="line" data-line="24">    <span style="color: #dbc074;">:gen_tcp</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">controlling_process</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">self</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="25">
</div><div class="line" data-line="26">    <span style="color: #dfdfe0;">n_data</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">conn: </span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">router: </span><span style="color: #dfdfe0;">router</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">pipeline: </span><span style="color: #dfdfe0;">pipeline</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">request: </span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">Request</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="27">
</div><div class="line" data-line="28">    <span style="color: #86abdc;">set_next_step</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">n_data</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="29">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="30">
</div><div class="line" data-line="31">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">event</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:noread</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_name</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">fun</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="32">    <span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">fun</span><span style="color: #aeafb0;">.</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="33">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_request</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="34">        <span style="color: #86abdc;">set_next_step</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">n_request</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:event</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">event</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="35">
</div><div class="line" data-line="36">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:error</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">reason</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="37">        <span style="color: #dfdfe0;">response</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Response</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">error_resp</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;</span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span> <span style="color: #dfdfe0;">reason</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="38">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:response</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">response: </span><span style="color: #dfdfe0;">response</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:send_response</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="39">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="40">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="41">
</div><div class="line" data-line="42">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">event</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:check</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_name</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">fun</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="43">    <span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">fun</span><span style="color: #aeafb0;">.</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="44">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_request</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="45">        <span style="color: #86abdc;">set_next_step</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">n_request</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:event</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">event</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="46">
</div><div class="line" data-line="47">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:dispatch</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_request</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="48">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:dispatching</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">n_request</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:dispatch</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="49">
</div><div class="line" data-line="50">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:response</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">response</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="51">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:response</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">response: </span><span style="color: #dfdfe0;">response</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:send_response</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="52">
</div><div class="line" data-line="53">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:error</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">reason</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="54">        <span style="color: #dfdfe0;">response</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Response</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">error_resp</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;</span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span> <span style="color: #dfdfe0;">reason</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="55">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:response</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">response: </span><span style="color: #dfdfe0;">response</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:send_response</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="56">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="57">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="58">
</div><div class="line" data-line="59">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:read</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">conn: </span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="60">    <span style="color: #9d79d6;">case</span> <span style="color: #dbc074;">:gen_tcp</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">recv</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">0</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">1000</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="61">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">packet</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="62">        <span style="color: #7ad5d6;">IO</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">inspect</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">packet</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">label: </span><span style="color: #81b29a;">&quot;packet&quot;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="63">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:keep_state_and_data</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:parse</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">packet</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="64">
</div><div class="line" data-line="65">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:error</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">reason</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="66">        <span style="color: #dfdfe0;">response</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Response</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">error_resp</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;</span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span> <span style="color: #dfdfe0;">reason</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="67">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:response</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">response: </span><span style="color: #dfdfe0;">response</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:send_response</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="68">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="69">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="70">
</div><div class="line" data-line="71">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:parse</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">packet</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">name</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">fun</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="72">
</div><div class="line" data-line="73">    <span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">fun</span><span style="color: #aeafb0;">.</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">packet</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="74">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:cont</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_request</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_acc</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="75">        <span style="color: #7ad5d6;">IO</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">inspect</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:cont</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_request</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_acc</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="76">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">name</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">fun</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_acc</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">n_request</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:read</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="77">
</div><div class="line" data-line="78">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:done</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_request</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">remaining</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="79">        <span style="color: #7ad5d6;">IO</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">inspect</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:done</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_request</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">remaining</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="80">        <span style="color: #86abdc;">set_next_step</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">n_request</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">remaining</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="81">
</div><div class="line" data-line="82">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:error</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">reason</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="83">        <span style="color: #dfdfe0;">response</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Response</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">error_resp</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;</span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span> <span style="color: #dfdfe0;">reason</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="84">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:response</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">response: </span><span style="color: #dfdfe0;">response</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:send_response</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="85">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="86">    
</div><div class="line" data-line="87">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="88">
</div><div class="line" data-line="89">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:dispatch</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:dispatching</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">request: </span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">conn: </span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">router: </span><span style="color: #dfdfe0;">router</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="90">    <span style="color: #86abdc;">try_dispatch</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">router</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="91">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:waiting</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">conn: </span><span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:wait</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span> 
</div><div class="line" data-line="92">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="93">
</div><div class="line" data-line="94">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:send_response</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:response</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">conn: </span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">response: </span><span style="color: #dfdfe0;">response</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="95">    <span style="color: #86abdc;">try_send_response</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">response</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="96">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:waiting</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">conn: </span><span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:wait</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="97">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="98">
</div><div class="line" data-line="99">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">handle_event</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:close</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">conn: </span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="100">    <span style="color: #dbc074;">:gen_tcp</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">close</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="101">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:waiting</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">conn: </span><span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:wait</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="102">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="103">
</div><div class="line" data-line="104">
</div><div class="line" data-line="105">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">set_next_step</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">pipeline: </span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">h</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">remaining</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="106">
</div><div class="line" data-line="107">    <span style="color: #dfdfe0;">event</span> <span style="color: #aeafb0;">=</span> <span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">remaining</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="108">              <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #86abdc;">:read</span>
</div><div class="line" data-line="109">              <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:event</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">event</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #dfdfe0;">event</span>
</div><div class="line" data-line="110">              <span style="color: #738091;">_</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:parse</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">remaining</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="111">            <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="112">
</div><div class="line" data-line="113">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">h</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">data</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">pipeline: </span><span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">event</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="114">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="115">
</div><div class="line" data-line="116">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">set_next_step</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">pipeline: </span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_remaining</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="117">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_state</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:dispatching</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">data</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:next_event</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:internal</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:dispatch</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="118">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="119">
</div><div class="line" data-line="120">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">try_dispatch</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">router</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">verb: </span><span style="color: #dfdfe0;">verb</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">path: </span><span style="color: #dfdfe0;">path</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">host: </span><span style="color: #dfdfe0;">host</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="121">    <span style="color: #9d79d6;">case</span> <span style="color: #86abdc;">apply</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">router</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:route</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">verb</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">path</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">host</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="122">      <span style="color: #dfdfe0;">response</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #86abdc;">try_send_response</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">response</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="123">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="124">  <span style="color: #9d79d6;">rescue</span>
</div><div class="line" data-line="125">    <span style="color: #dfdfe0;">e</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #86abdc;">try_send_response</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Response</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">error_resp</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="126">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="127">
</div><div class="line" data-line="128">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">try_send_response</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">Response</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">response</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="129">    <span style="color: #dfdfe0;">n_response</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Response</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">make_resp</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">response</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="130">    <span style="color: #86abdc;">send_response</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_response</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="131">  <span style="color: #9d79d6;">after</span>
</div><div class="line" data-line="132">    <span style="color: #dbc074;">:gen_tcp</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">close</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="133">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="134">
</div><div class="line" data-line="135">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">try_send_response</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">response</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">response</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="136">    <span style="color: #86abdc;">send_response</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">response</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="137">  <span style="color: #9d79d6;">after</span>
</div><div class="line" data-line="138">    <span style="color: #dbc074;">:gen_tcp</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">close</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="139">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="140">
</div><div class="line" data-line="141">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">send_response</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">response</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="142">    <span style="color: #dbc074;">:gen_tcp</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">send</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">conn</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">response</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="143">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="144"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>And we need to define also, a module to handle responses, create a file <code>apps/satellite/lib/satellite_response.ex</code> with:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Satellite.Response</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3">  <span style="color: #9d79d6;">defstruct</span> <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">code: </span><span style="color: #f4a261;">200</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">headers: </span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;content-type&quot;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;text/html&quot;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">body: </span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="4">
</div><div class="line" data-line="5">  <span style="color: #f6b079;">@</span><span style="color: #f6b079;">codes </span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #f4a261;">200</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;OK&quot;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #f4a261;">404</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;Not Found&quot;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #f4a261;">500</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;Internal Server Error&quot;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="6">  
</div><div class="line" data-line="7">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">make_resp</span><span style="color: #aeafb0;">(</span>
</div><div class="line" data-line="8">    <span style="color: #7ad5d6;">%</span><span style="color: #f6b079;">__MODULE__</span><span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="9">      <span style="color: #86abdc;">code: </span><span style="color: #dfdfe0;">code</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="10">      <span style="color: #86abdc;">headers: </span><span style="color: #dfdfe0;">headers</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="11">      <span style="color: #86abdc;">body: </span><span style="color: #dfdfe0;">body</span>
</div><div class="line" data-line="12">    <span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="13">  <span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="14">
</div><div class="line" data-line="15">    <span style="color: #dfdfe0;">code_prep</span> <span style="color: #aeafb0;">=</span> <span style="color: #86abdc;">make_code</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">code</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="16">    <span style="color: #dfdfe0;">headers_prep</span> <span style="color: #aeafb0;">=</span> <span style="color: #86abdc;">map_headers</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">headers</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="17">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">n_body</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">content_length_prep</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #86abdc;">create_length</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">body</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="18">    
</div><div class="line" data-line="19">    <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;HTTP/1.0 &quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">code_prep</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;</span><span style="color: #e0c989; font-weight: bold;">\n</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">headers_prep</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">content_length_prep</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;</span><span style="color: #e0c989; font-weight: bold;">\n</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">n_body</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">&gt;&gt;</span>
</div><div class="line" data-line="20">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="21">
</div><div class="line" data-line="22">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">map_headers</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">headers</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">map_headers</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">headers</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="23">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">map_headers</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">header</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">value</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">map_headers</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">header</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;: &quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">value</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;</span><span style="color: #e0c989; font-weight: bold;">\n</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="24">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">map_headers</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #dfdfe0;">acc</span>
</div><div class="line" data-line="25">  
</div><div class="line" data-line="26">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">create_length</span><span style="color: #aeafb0;">(</span><span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;content-length: 0&quot;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="27">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">create_length</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;content-length: 0&quot;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="28">  <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">create_length</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">body</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="29">    <span style="color: #dfdfe0;">size</span> <span style="color: #aeafb0;">=</span> <span style="color: #dbc074;">:erlang</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">integer_to_binary</span><span style="color: #aeafb0;">(</span><span style="color: #dbc074;">:erlang</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">size</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">body</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="30">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">body</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;content-length: &quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">size</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;</span><span style="color: #e0c989; font-weight: bold;">\n</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="31">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="32">
</div><div class="line" data-line="33">
</div><div class="line" data-line="34">  <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">each</span><span style="color: #aeafb0;">(</span><span style="color: #f6b079;">@</span><span style="color: #f6b079;">codes</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">code</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">val</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="35">
</div><div class="line" data-line="36">    <span style="color: #dfdfe0;">string_v</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">Integer</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_string</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">code</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="37">    <span style="color: #dfdfe0;">atom_v</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">String</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">to_atom</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">string_v</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="38">
</div><div class="line" data-line="39">    <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">make_code</span><span style="color: #aeafb0;">(</span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">code</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">string_v</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot; &quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">val</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">&gt;&gt;</span>
</div><div class="line" data-line="40">    <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">make_code</span><span style="color: #aeafb0;">(</span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">string_v</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">string_v</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot; &quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">val</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">&gt;&gt;</span>
</div><div class="line" data-line="41">    <span style="color: #9d79d6;">defp</span> <span style="color: #86abdc;">make_code</span><span style="color: #aeafb0;">(</span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">atom_v</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">string_v</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot; &quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">unquote</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">val</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">&gt;&gt;</span>
</div><div class="line" data-line="42">
</div><div class="line" data-line="43">  <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="44">
</div><div class="line" data-line="45">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">error_resp</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">body</span> <span style="color: #aeafb0;">\\</span> <span style="color: #81b29a;">&quot;Internal Server Error&quot;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="46">    <span style="color: #7ad5d6;">%</span><span style="color: #f6b079;">__MODULE__</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">code: </span><span style="color: #f4a261;">500</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">headers: </span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;content-type&quot;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;text/html&quot;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">body: </span><span style="color: #dfdfe0;">body</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="47">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="48">
</div><div class="line" data-line="49">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">not_found</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">body</span> <span style="color: #aeafb0;">\\</span> <span style="color: #81b29a;">&quot;Not Found&quot;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="50">    <span style="color: #7ad5d6;">%</span><span style="color: #f6b079;">__MODULE__</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">code: </span><span style="color: #f4a261;">404</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">headers: </span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;content-type&quot;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;text/html&quot;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">body: </span><span style="color: #dfdfe0;">body</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="51">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="52">  
</div><div class="line" data-line="53"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>And lastly, just to test that everything goes according to plan, lets create a test router and a controller for it. <code>apps/satellite/lib/test_router.ex</code>:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Test.Router</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">  <span style="color: #9d79d6;">use</span> <span style="color: #7ad5d6;">Satellite.Routing</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4">  <span style="color: #86abdc;">route</span> <span style="color: #81b29a;">&quot;get&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;/&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Test.Controller</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:test</span>
</div><div class="line" data-line="5">  <span style="color: #86abdc;">route</span> <span style="color: #81b29a;">&quot;get&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;/:any/oi/:some&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Test.Controller</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:test2</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;*&quot;</span>
</div><div class="line" data-line="6">  <span style="color: #86abdc;">route</span> <span style="color: #81b29a;">&quot;get&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;*&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Test.Controller</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:test3</span>
</div><div class="line" data-line="7">  <span style="color: #86abdc;">route</span> <span style="color: #81b29a;">&quot;post&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;/data&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Test.Controller</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:test4</span>
</div><div class="line" data-line="8"><span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="9">
</div><div class="line" data-line="10"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Test.Controller</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="11">
</div><div class="line" data-line="12">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">test</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="13">    <span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">Satellite.Response</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">body: </span><span style="color: #81b29a;">&quot;this is the root path, nothing to see here&quot;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="14">    <span style="color: #aeafb0;">|&gt;</span> <span style="color: #7ad5d6;">Satellite.Response</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">make_resp</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="15">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="16">
</div><div class="line" data-line="17">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">test2</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="18">    <span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">Satellite.Response</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">body: </span><span style="color: #81b29a;">&quot;</span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span> <span style="color: #dfdfe0;">request</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="19">    <span style="color: #aeafb0;">|&gt;</span> <span style="color: #7ad5d6;">Satellite.Response</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">make_resp</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="20">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="21">
</div><div class="line" data-line="22">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">test3</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="23">     <span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">Satellite.Response</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">body: </span><span style="color: #81b29a;">&quot;&quot;&quot;
</div><div class="line" data-line="24">	&lt;html&gt;&lt;body&gt;&lt;h1&gt;Wildcard match!&lt;/h1&gt;&lt;br&gt;&lt;br&gt;&lt;div style=&quot;color: red;&quot;&gt;</span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span> <span style="color: #dfdfe0;">request</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;
</div><div class="line" data-line="25">      &quot;&quot;&quot;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="26">      <span style="color: #aeafb0;">|&gt;</span> <span style="color: #7ad5d6;">Satellite.Response</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">make_resp</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="27">   <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="28">  
</div><div class="line" data-line="29">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">test4</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">body: </span><span style="color: #dfdfe0;">parsed_body</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="30">     <span style="color: #dfdfe0;">response_body</span> <span style="color: #aeafb0;">=</span>  <span style="color: #81b29a;">&quot;Parsed: &quot;</span> <span style="color: #aeafb0;">&lt;&gt;</span> <span style="color: #7ad5d6;">Jason</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">encode!</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">parsed_body</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">&lt;&gt;</span> <span style="color: #81b29a;">&quot;</span><span style="color: #e0c989; font-weight: bold;">\n</span><span style="color: #81b29a;">&quot;</span>
</div><div class="line" data-line="31">     <span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">Satellite.Response</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">body: </span><span style="color: #dfdfe0;">response_body</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">headers: </span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;content-type&quot;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;application/json&quot;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="32">     <span style="color: #aeafb0;">|&gt;</span> <span style="color: #7ad5d6;">Satellite.Response</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">make_resp</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="33">   <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="34">
</div><div class="line" data-line="35"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Since we'll also want to test <code>post</code> requests and we'll use <code>Jason</code> to encode JSON, we might as well go ahead and add the last bit to our pipeline, the body parser. Right now we'll only do it for JSON.</p>
<p>On <code>apps/satellite/lib/satellite_defaults.ex</code> add the following <code>&lbrace;:read, :body, &amp;Satellite.Body.parse/3, &lbrace;0, &lt;&lt;&gt;&gt;&rbrace;&rbrace;</code></p>
<p>The full pipeline should now look like:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Satellite.Defaults</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">  
</div><div class="line" data-line="3">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">default_pipeline</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="4">    <span style="color: #aeafb0;">[</span>
</div><div class="line" data-line="5">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:read</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:verb</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #7ad5d6;">Satellite.Verb</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">/</span><span style="color: #aeafb0;">3</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="6">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:read</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:path</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #7ad5d6;">Satellite.Path</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">/</span><span style="color: #aeafb0;">3</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #f4a261;">false</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="7">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:read</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:conn</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #7ad5d6;">Satellite.Conn</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">/</span><span style="color: #aeafb0;">3</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="8">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:read</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:headers</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #7ad5d6;">Satellite.Headers</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">/</span><span style="color: #aeafb0;">3</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:header</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="9">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:noread</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:host</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #7ad5d6;">Satellite.Host</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">set</span><span style="color: #aeafb0;">/</span><span style="color: #aeafb0;">2</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="10">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:noread</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:accept</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #7ad5d6;">Satellite.Accept</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">set</span><span style="color: #aeafb0;">/</span><span style="color: #aeafb0;">2</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="11">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:check</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:check_request_type</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #7ad5d6;">Satellite.Check</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">check</span><span style="color: #aeafb0;">/</span><span style="color: #aeafb0;">2</span><span style="color: #aeafb0;">,</span> <span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="12">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:read</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:body</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&amp;</span><span style="color: #7ad5d6;">Satellite.Body</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">/</span><span style="color: #aeafb0;">3</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #f4a261;">0</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="13">    <span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="14">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="15">  
</div><div class="line" data-line="16"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>(note: we kept it as tuples, because tuples are the fastest way to access something, if in erlang we would use <code>Records</code> which are still tuples underneath and in Elixir we would use proper structs to encode this, something like <code>%Satellite.Step&lbrace;mode: :read, name: :verb, fun: &amp;Satellite.Verb.parse/3, acc: &lt;&lt;&gt;&gt;&rbrace;</code>, this would be much more structured, specially with <code>@enforce_keys</code> we could give some guarantees on when placing a step in the pipeline but that's all out of scope for this tutorial)</p>
<p>And create the file <code>apps/satellite/lib/satellite_body.ex</code>:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Satellite.Body</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">verb: </span><span style="color: #86abdc;">:post</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">headers: </span><span style="color: #dfdfe0;">headers</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">count</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="4">    <span style="color: #dfdfe0;">n_size</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">count</span> <span style="color: #aeafb0;">+</span> <span style="color: #dbc074;">:erlang</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">size</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="5">    <span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">headers</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="6">      <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;content-length&quot;</span><span style="color: #aeafb0;">&gt;&gt;</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #f4a261;">0</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:done</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="7">      <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;content-length&quot;</span><span style="color: #aeafb0;">&gt;&gt;</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #aeafb0;">^</span><span style="color: #dfdfe0;">n_size</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="8">        <span style="color: #9d79d6;">case</span> <span style="color: #86abdc;">parse_content</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">headers</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="9">          <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:ok</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">decoded</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:done</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">request</span> <span style="color: #aeafb0;">|</span> <span style="color: #86abdc;">body: </span><span style="color: #dfdfe0;">decoded</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="10">          <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:error</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">error</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:error</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">error</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="11">        <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="12">      <span style="color: #738091;">_</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="13">        <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:cont</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">n_size</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">bits</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="14">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="15">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="16">
</div><div class="line" data-line="17">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:done</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="18">
</div><div class="line" data-line="19">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">parse_content</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;content-type&quot;</span><span style="color: #aeafb0;">&gt;&gt;</span> <span style="color: #aeafb0;">=&gt;</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;application/json&quot;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="20">    <span style="color: #7ad5d6;">Jason</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">decode</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">rem</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="21">    <span style="color: #9d79d6;">catch</span> <span style="color: #dfdfe0;">e</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:error</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">e</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="22">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="23">  
</div><div class="line" data-line="24"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Lastly, we need to add Jason as a dependency so we can use it, on <code>apps/satellite/mix.exs</code> change your <code>deps</code> function to this:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defp</span> <span style="color: #dfdfe0;">deps</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">    <span style="color: #aeafb0;">[</span>
</div><div class="line" data-line="3">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:satellite_shared</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">in_umbrella: </span><span style="color: #f4a261;">true</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="4">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:jason</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;~&gt; 1.0&quot;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="5">    <span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="6"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>After that, save the file, quit the shell and do:</p>
<p><code>mix deps.get</code></p>
<p>This will install the dependencies.</p>
<p>With this in place, let's exit the shell, restart it with <code>iex -S mix run</code> and then do <code>Launchpad.start_link(%Satellite.Configuration&lbrace;router: Test.Router&rbrace;)</code></p>
<p>Now visit <code>http://localhost:4000</code>, <code>http://localhost:4000/something/oi/else</code> and <code>http://localhost:4000/anything_goes</code></p>
<p>You should see the correct ouput in the browser.</p>
<p>Now to test <code>post</code>s we'll use <code>curl</code> with the <code>-v</code> flag (verbose) option to see if it works. Open a new terminal window (but don't close the one running the server ofc), and execute:</p>
<p><code>curl -v -d '&lbrace;&quot;key1&quot;:&quot;value1&quot;, &quot;key2&quot;:&quot;value2&quot;&rbrace;' -H &quot;Content-Type: application/json&quot; -X POST http://localhost:4000/data</code></p>
<p>You should see an output of the request details, finished by:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #aeafb0;">*</span> <span style="color: #86abdc;">upload</span> <span style="color: #86abdc;">completely</span> <span style="color: #86abdc;">sent</span> <span style="color: #86abdc;">off: </span><span style="color: #f4a261;">34</span> <span style="color: #86abdc;">out</span> <span style="color: #86abdc;">of</span> <span style="color: #f4a261;">34</span> bytes
</div><div class="line" data-line="2"><span style="color: #aeafb0;">*</span> <span style="color: #7ad5d6;">HTTP</span> <span style="color: #f4a261;">1.0</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">assume</span> <span style="color: #86abdc;">close</span> <span style="color: #86abdc;">after</span> <span style="color: #dfdfe0;">body</span>
</div><div class="line" data-line="3"><span style="color: #aeafb0;">&lt;</span> <span style="color: #7ad5d6;">HTTP</span><span style="color: #aeafb0;">/</span><span style="color: #f4a261;">1.0</span> <span style="color: #f4a261;">200</span> OK
</div><div class="line" data-line="4"><span style="color: #aeafb0;">&lt;</span> <span style="color: #dfdfe0;">content</span><span style="color: #aeafb0;">-</span><span style="color: #86abdc;">type</span>: <span style="color: #dfdfe0;">application</span><span style="color: #aeafb0;">/</span><span style="color: #dfdfe0;">json</span>
</div><div class="line" data-line="5"><span style="color: #aeafb0;">&lt;</span> <span style="color: #dfdfe0;">content</span><span style="color: #aeafb0;">-</span><span style="color: #86abdc;">length</span>: <span style="color: #f4a261;">42</span>
</div><div class="line" data-line="6"><span style="color: #aeafb0;">&lt;</span> 
</div><div class="line" data-line="7"><span style="color: #7ad5d6;">Parsed</span>: <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">&quot;key1&quot;</span><span style="color: #86abdc;">:&quot;value1&quot;</span><span style="color: #aeafb0;">,</span><span style="color: #86abdc;">&quot;key2&quot;</span><span style="color: #86abdc;">:&quot;value2&quot;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="8"><span style="color: #7ad5d6;">Closing</span> <span style="color: #86abdc;">connection</span> <span style="color: #f4a261;">0</span>
</div></code></pre>
<p>If you try:</p>
<p><code>curl -v -d 'oiioi' -H &quot;Content-Type: application/json&quot; -X POST http://localhost:4000/data</code></p>
<p>You should see instead:</p>
<p><code>%Jason.DecodeError&lbrace;data: &quot;oiioi&quot;, position: 0, token: nil&rbrace;</code>  as the response, which is the error from trying to parse invalid json <code>&quot;oiioi&quot;</code>. Of course this is also not how it should in reality be implemented, it should not leak the details of what is wrong internally, but we wrote it in such a way to illustrate that although the request raised an error, it was still answered.</p>
<p>Now one last thing is to see if we can use this on another app. So let's remove the file <code>apps/satellite/lib/test_router.ex</code>, go outside the folder of the umbrella and create a new app, with <code>mix new test_satellitex --sup</code></p>
<p>Then add to <code>test_satellitex/lib</code> two files, <code>router.ex</code> and <code>controller.ex</code>, on <code>router.ex</code> add:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Router</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">  <span style="color: #9d79d6;">use</span> <span style="color: #7ad5d6;">Satellite.Routing</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4">  <span style="color: #86abdc;">route</span> <span style="color: #81b29a;">&quot;get&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;/&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Controller</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:test</span>
</div><div class="line" data-line="5">  <span style="color: #86abdc;">route</span> <span style="color: #81b29a;">&quot;get&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;/:any/oi/:some&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Controller</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:test2</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;*&quot;</span>
</div><div class="line" data-line="6">  <span style="color: #86abdc;">route</span> <span style="color: #81b29a;">&quot;get&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;*&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Controller</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:test3</span>
</div><div class="line" data-line="7">  <span style="color: #86abdc;">route</span> <span style="color: #81b29a;">&quot;post&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;/data&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">Controller</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:test4</span>
</div><div class="line" data-line="8"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>And on <code>controller.ex</code> add:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">Controller</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">test</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="4">    <span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">Satellite.Response</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">body: </span><span style="color: #81b29a;">&quot;</span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span> <span style="color: #dfdfe0;">request</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="5">    <span style="color: #aeafb0;">|&gt;</span> <span style="color: #7ad5d6;">Satellite.Response</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">make_resp</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="6">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="7">
</div><div class="line" data-line="8">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">test2</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="9">    <span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">Satellite.Response</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">body: </span><span style="color: #81b29a;">&quot;</span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span> <span style="color: #dfdfe0;">request</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="10">    <span style="color: #aeafb0;">|&gt;</span> <span style="color: #7ad5d6;">Satellite.Response</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">make_resp</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="11">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="12">
</div><div class="line" data-line="13">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">test3</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">request</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="14">    <span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">Satellite.Response</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">body: </span><span style="color: #81b29a;">&quot;&quot;&quot;
</div><div class="line" data-line="15">    &lt;html&gt;&lt;body&gt;&lt;h1&gt;Wildcard match!&lt;/h1&gt;&lt;br&gt;&lt;br&gt;&lt;div style=&quot;color: red;&quot;&gt;</span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span> <span style="color: #dfdfe0;">request</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;
</div><div class="line" data-line="16">    &quot;&quot;&quot;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="17">    <span style="color: #aeafb0;">|&gt;</span> <span style="color: #7ad5d6;">Satellite.Response</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">make_resp</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="18">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="19">
</div><div class="line" data-line="20">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">test4</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">body: </span><span style="color: #dfdfe0;">parsed_body</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="21">    <span style="color: #dfdfe0;">response_body</span> <span style="color: #aeafb0;">=</span> <span style="color: #81b29a;">&quot;Parsed: &quot;</span> <span style="color: #aeafb0;">&lt;&gt;</span> <span style="color: #7ad5d6;">Jason</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">encode!</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">parsed_body</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">&lt;&gt;</span> <span style="color: #81b29a;">&quot;</span><span style="color: #e0c989; font-weight: bold;">\n</span><span style="color: #81b29a;">&quot;</span>
</div><div class="line" data-line="22">    <span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">Satellite.Response</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">body: </span><span style="color: #dfdfe0;">response_body</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">headers: </span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;content-type&quot;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #81b29a;">&quot;application/json&quot;</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="23">    <span style="color: #aeafb0;">|&gt;</span> <span style="color: #7ad5d6;">Satellite.Response</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">make_resp</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="24">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="25">
</div><div class="line" data-line="26"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>On <code>test_satellitex/mix.exs</code> change the deps to:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defp</span> <span style="color: #dfdfe0;">deps</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">    <span style="color: #aeafb0;">[</span>
</div><div class="line" data-line="3">      <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:satellitex</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">path: </span><span style="color: #81b29a;">&quot;../satellitex&quot;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="4">    <span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="5"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>(assuming you created the <code>test_satellitex</code> app on the same folder level as <code>satellitex</code>, if not change the relative path accordingly).
We're using a local path just to test, in a real situation this would be either in git or hex and you would use either a git path or a normal dep definition.</p>
<p>Save the file, and edit <code>test_satellitex/lib/test_satellitex/application.ex</code> to:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">TestSatellitex.Application</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">  <span style="color: #738091;">@</span><span style="color: #738091;">moduledoc</span> <span style="color: #738091;">false</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4">  <span style="color: #9d79d6;">use</span> <span style="color: #7ad5d6;">Application</span>
</div><div class="line" data-line="5">
</div><div class="line" data-line="6">  <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">start</span><span style="color: #aeafb0;">(</span><span style="color: #738091;">_type</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_args</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="7">    <span style="color: #dfdfe0;">children</span> <span style="color: #aeafb0;">=</span> <span style="color: #aeafb0;">[</span>
</div><div class="line" data-line="8">      <span style="color: #7ad5d6;">Supervisor</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">child_spec</span><span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">id: </span><span style="color: #7ad5d6;">Server1</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">start: </span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #7ad5d6;">Launchpad</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:start_link</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">Satellite.Configuration</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">router: </span><span style="color: #7ad5d6;">Router</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">type: </span><span style="color: #86abdc;">:worker</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="9">    <span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="10">
</div><div class="line" data-line="11">    <span style="color: #dfdfe0;">opts</span> <span style="color: #aeafb0;">=</span> <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">strategy: </span><span style="color: #86abdc;">:one_for_one</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">name: </span><span style="color: #7ad5d6;">TestSatellitex.Supervisor</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="12">    <span style="color: #7ad5d6;">Supervisor</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">start_link</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">children</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">opts</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="13">  <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="14"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Then from the root dir of this app do <code>mix deps.get</code> to install the dependencies.
And then start it with:</p>
<p><code>iex -S mix run</code></p>
<p>And you should have a running server on another application.</p>
<p>And that's it! This post is already gigantic, so we'll stop here. It's very, very far from being a compliant http server, there's many things missing but the general structure is laid out, about what is missing:</p>
<ul>
<li>parsing cookies!</li>
<li>serving static assets</li>
<li>appropriate response handlers for different formats other than html/json</li>
<li>mime support</li>
<li>html full range of response codes</li>
<li>http protocol version negotiation</li>
<li>ssl/tls</li>
<li>websockets</li>
<li>another type of callback in our gen_statem besides <code>:read</code>, <code>:noread</code> and <code>:check</code>, probably named <code>:connection</code> where the called function receives the request and the socket itself, so if wanted it could retrieve information from the socket such as the peer_address (ip address of whoever is making the request, amongst other things) - this would allow to easily create a rate-limiter as the first step of the pipeline, if wanted without actually reading anything from the socket</li>
<li>preparing templates &amp; &quot;views&quot; to send as responses</li>
<li>defining the pipeline elements as behaviours so that it would be easier to understand what you need to do to have a &quot;compliant&quot; pipeline step created</li>
</ul>
<p>And many of those are really grunt work, extensive research (reading the RFC's and making the implementation be spec compliant) and/or tricky to implement correctly, so hopefully, besides having learned some things about gen_statems, erlang and elixir it also increased your appreciation for the existing libraries that do all of this, correctly and efficiently and available for free!</p> ]]></description>
    </item>
    <item>
       <title>Pattern Matching in Elixir - Does it fit?</title>
       <link>https://micaelnussbaumer.com/posts/pattern-matching-in-elixir</link>
       <pubDate>Sat, 11 May 2019 01:00:00 UTC</pubDate>
       <guid>https://micaelnussbaumer.com/posts/pattern-matching-in-elixir</guid>
       <description><![CDATA[ <p>Pattern matching is a very powerful feature in any programming language that implements it, I think that essentially because pattern matching is inherent in computer programming logic, from a conceptual to a practical level. It's a feature that is present in many functional languages for the programmer to use. Elixir (inheriting from Erlang) gives us access to it and idiomatic code is most often peppered with pattern matching.</p>
<p>It fits well in many places and allows us to describe very succinctly the code paths our running programs may take, while retaining, and most of the time increasing, the clarity of the code. While some features that allow succinctness and conciseness of code end up in a symbolical soup more close to mathematics than a &quot;legible&quot; declaration (for those of us not completely familiar with mathematical notation), pattern matching does not suffer from that, because what it allows us to express is the &quot;form&quot; of the data inside our running programs, which in turn allows us to express what pathways of code should be run given that form.</p>
<p>Erlang itself has on top of that a very accessible and intuitive way of treating binary data, that coupled with pattern matching gives it the ability to chop, split, and work with binaries in a very pleasant way.</p>
<p>Now I could go on talking about how the rainbow is perfect during this sunset, or how unicorns are pooping diamonds and so on, but that won't give you any insight into Pattern Matching. So let's move to do some exploration of it.</p>
<p>First we'll start by analysing the <code>=</code> operator in Elixir, which is in fact a match operator and not an assignment operator (if you're coming from Javascript, Ruby, etc). It has one side effect that makes it look like an assignment operator though, which is, when the expression on the left side of it is a <code>variable</code>, it binds whatever is on the right side to that variable.</p>
<p>We can do some simple tests of it on iex:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #f4a261;">1</span> <span style="color: #aeafb0;">=</span> <span style="color: #f4a261;">1</span>
</div><div class="line" data-line="2"><span style="color: #738091;"># 1</span>
</div><div class="line" data-line="3"><span style="color: #f4a261;">1</span> <span style="color: #aeafb0;">=</span> <span style="color: #f4a261;">2</span>
</div><div class="line" data-line="4"><span style="color: #738091;"># ** (MatchError) no match of right hand side value: 2</span>
</div><div class="line" data-line="5">
</div><div class="line" data-line="6"><span style="color: #dfdfe0;">a</span> <span style="color: #aeafb0;">=</span> <span style="color: #f4a261;">1</span>
</div><div class="line" data-line="7"><span style="color: #738091;"># 1</span>
</div><div class="line" data-line="8">
</div><div class="line" data-line="9"><span style="color: #dfdfe0;">a</span> <span style="color: #aeafb0;">=</span> <span style="color: #f4a261;">2</span>
</div><div class="line" data-line="10"><span style="color: #738091;"># 2</span>
</div><div class="line" data-line="11">
</div><div class="line" data-line="12"><span style="color: #dfdfe0;">a</span> <span style="color: #aeafb0;">+</span> <span style="color: #f4a261;">1</span>
</div><div class="line" data-line="13"><span style="color: #738091;"># 3</span>
</div><div class="line" data-line="14">
</div><div class="line" data-line="15"><span style="color: #dfdfe0;">a</span>
</div><div class="line" data-line="16"><span style="color: #738091;"># 2</span>
</div><div class="line" data-line="17">
</div><div class="line" data-line="18"><span style="color: #f4a261;">3</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">a</span>
</div><div class="line" data-line="19"><span style="color: #738091;">#** (MatchError) no match of right hand side value: 2</span>
</div><div class="line" data-line="20">
</div><div class="line" data-line="21"><span style="color: #dfdfe0;">a</span> <span style="color: #aeafb0;">=</span> <span style="color: #f4a261;">3</span>
</div><div class="line" data-line="22"><span style="color: #738091;"># 3</span>
</div><div class="line" data-line="23">
</div><div class="line" data-line="24"><span style="color: #dfdfe0;">a</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">a</span> <span style="color: #aeafb0;">+</span> <span style="color: #f4a261;">1</span>
</div><div class="line" data-line="25"><span style="color: #738091;"># 4</span>
</div><div class="line" data-line="26">
</div><div class="line" data-line="27"><span style="color: #dfdfe0;">a</span>
</div><div class="line" data-line="28"><span style="color: #738091;"># 4</span>
</div></code></pre>
<p>Ok, so what can we see from these examples? First we see that when a match evaluates correctly, we get the value of the expression that was matched. <code>1 = 1</code> returns 1, and not true. If we wanted to check for equality we would use the equality operator <code>==</code> and not the match operator <code>=</code>.</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #aeafb0;">&gt;</span> <span style="color: #f4a261;">1</span> <span style="color: #aeafb0;">==</span> <span style="color: #f4a261;">1</span>
</div><div class="line" data-line="2"><span style="color: #738091;"># true</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4"><span style="color: #aeafb0;">&gt;</span> <span style="color: #f4a261;">1</span> <span style="color: #aeafb0;">==</span> <span style="color: #f4a261;">2</span>
</div><div class="line" data-line="5"><span style="color: #738091;"># false</span>
</div></code></pre>
<p>On the second case we get a <code>MatchError</code>, because we're trying to convince our program that <code>1</code> matches <code>2</code>, and it simply states, dude, perhaps in your universe, but in mine, 1 can't match 2.</p>
<p>Then we do a bunch of &quot;assignments&quot;, and it works mostly as one would expect in other languages, the variable <code>a</code> gets bound to whatever  value.</p>
<p>When we try to do <code>3 = a</code>, when <code>a</code> was bound to 2, we get again an error, but when we switch it to <code>a = 3</code> we no longer get an error, instead the value 3 is bound to the variable <code>a</code>.</p>
<p>In Erlang you can't use the same variable name in different assignments, but Elixir chose to allow it. Underneath, because the data is still immutable, what happens is that elixir creates various versions of <code>a</code>  and points <code>a</code> to the last version you entered - from a practical point of view though, it looks like you're &quot;re-assigning&quot; the variable.</p>
<p>Now you might be thinking, all of that for what?
Yes, it's not apparent yet why it helps in anything else other than silly examples. So let's move on.</p>
<p>Let's create a map and play around with it.</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #dfdfe0;">a</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">key_one: </span><span style="color: #81b29a;">&quot;this is key number one&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">key_two: </span><span style="color: #81b29a;">&quot;this is key number two&quot;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="2"><span style="color: #738091;"># %&lbrace;key_one: &quot;this is key number one&quot;, key_two: &quot;this is key number two&quot;&rbrace;</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4"><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">key_one: </span><span style="color: #dfdfe0;">key_one_var</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">a</span>
</div><div class="line" data-line="5"><span style="color: #738091;"># %&lbrace;key_one: &quot;this is key number one&quot;, key_two: &quot;this is key number two&quot;&rbrace;</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7"><span style="color: #dfdfe0;">key_one_var</span>
</div><div class="line" data-line="8"><span style="color: #738091;"># &quot;this is key number one&quot;</span>
</div></code></pre>
<p>So here things start to look more interesting. You can see that we placed a pattern of <code>%&lbrace;key_one: key_one_var&rbrace;</code> and matched it against the previously map bound to <code>a</code>. The match succeeded, but we also &quot;bound&quot; the variable <code>key_one_var</code> to whatever was the value of the key <code>:key_one</code> used in the pattern match.
If you used Javascript E6 destructuring you might notice it looks familiar. The Erlang (&amp;Elixir) version though is way more powerful than javascript's version, because of its properties and how it can be used, but lets move on.</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">key_three: </span><span style="color: #dfdfe0;">key_three_var</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">a</span>
</div><div class="line" data-line="2"><span style="color: #738091;"># ** (MatchError) no match of right hand side value: %&lbrace;key_one: &quot;this is key number one&quot;, key_two: &quot;this is key number two&quot;&rbrace;</span>
</div></code></pre>
<p>Ok, we tried to match the map bound to <code>a</code> to a map of the form <code>%&lbrace;key_three: some_variable&rbrace;</code> and this didn't work, because <code>a</code> doesn't have any key named <code>:key_three</code>, it's expected to fail.
But notice that we didn't need to specify all the keys when matching <code>:key_one</code> previously, although the <code>a</code> map had an additional <code>:key_two</code>.</p>
<p>So how can we look at it conceptually? I think that the best way to describe it is, given <code>a = b</code>, could the form described in <code>a</code> be extracted from the contents held in <code>b</code>? If it can the match succeeds, any bindings are made effective, and the full expression is returned. If it can't, an error is thrown.</p>
<p>And in this case indeed it can, in the previous example, the form <code>map, with a key named :key_one, to be bound to a variable named key_one_var</code> can be extracted from <code>a</code>, because that map has a key named <code>:key_one</code> and we aren't specifying any value that that key must have.</p>
<p>So if we write:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">key_one: </span><span style="color: #81b29a;">&quot;this is key number one&quot;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">a</span>
</div></code></pre>
<p>It also matches. But if we write:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">key_one: </span><span style="color: #81b29a;">&quot;this is key number two&quot;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">a</span>
</div><div class="line" data-line="2"><span style="color: #aeafb0;">**</span> <span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">MatchError</span><span style="color: #aeafb0;">)</span> <span style="color: #86abdc;">no</span> <span style="color: #86abdc;">match</span> <span style="color: #86abdc;">of</span> <span style="color: #86abdc;">right</span> <span style="color: #86abdc;">hand</span> <span style="color: #86abdc;">side</span> <span style="color: #86abdc;">value: </span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">key_one: </span><span style="color: #81b29a;">&quot;this is key number one&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">key_two: </span><span style="color: #81b29a;">&quot;this is key number two&quot;</span><span style="color: #aeafb0;">&rbrace;</span>
</div></code></pre>
<p>It fails, because we're saying match a map that has a key named <code>:key_one</code> with the value <code>&quot;this is key number two&quot;</code>, but since the value of that key in <code>a</code> is actually <code>&quot;this is key number one&quot;</code> it fails.</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">key_one: </span><span style="color: #81b29a;">&quot;this is key number &quot;</span> <span style="color: #aeafb0;">&lt;&gt;</span> <span style="color: #dfdfe0;">keynumber</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">a</span>
</div><div class="line" data-line="2"><span style="color: #738091;"># %&lbrace;key_one: &quot;this is key number one&quot;, key_two: &quot;this is key number two&quot;&rbrace;</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4"><span style="color: #dfdfe0;">keynumber</span>
</div><div class="line" data-line="5"><span style="color: #738091;"># &quot;one&quot;</span>
</div></code></pre>
<p>Here it matches, and not only that, we have extracted the last portion of the binary string as a variable. We could extract both the last portion and the whole binary string if we wanted with for instance:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">key_one: </span><span style="color: #81b29a;">&quot;this is key number &quot;</span> <span style="color: #aeafb0;">&lt;&gt;</span> <span style="color: #dfdfe0;">keynumber</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">whole_binary</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">a</span>
</div><div class="line" data-line="2"><span style="color: #738091;"># %&lbrace;key_one: &quot;this is key number one&quot;, key_two: &quot;this is key number two&quot;&rbrace;</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4"><span style="color: #dfdfe0;">keynumber</span>
</div><div class="line" data-line="5"><span style="color: #738091;"># &quot;one&quot;</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7"><span style="color: #dfdfe0;">whole_binary</span>
</div><div class="line" data-line="8"><span style="color: #738091;"># &quot;this is key number one&quot;</span>
</div></code></pre>
<p>It doesn't end here though, because the patterns you use can be much more complex and involve nested levels of maps, binary specifications, and lists, and so on, you can &quot;describe&quot; in as much detail as you want their forms and also extract very easily what you need from them.</p>
<p><code>%&lbrace;&rbrace; = a</code></p>
<p>Matches alright again, because we're simply saying, is the value bound to <code>a</code> a map? And since it is, all is good. You might have thought that it would fail, because <code>%&lbrace;&rbrace;</code> could be interpreted as an <code>empty</code> map but maps behave in this regard a bit differently. To assert that a map is indeed empty, you need to compare it, <code>%&lbrace;&rbrace; == a</code> would return <code>false</code> for instance.</p>
<p>Now lists:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #dfdfe0;">b</span> <span style="color: #aeafb0;">=</span> <span style="color: #aeafb0;">[</span><span style="color: #81b29a;">&quot;a&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;list&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:of</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:stuff</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="2"><span style="color: #738091;"># [&quot;a&quot;, &quot;list&quot;, :of, :stuff]</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4"><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">head</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">tail</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">b</span>
</div><div class="line" data-line="5"><span style="color: #738091;"># [&quot;a&quot;, &quot;list&quot;, :of, :stuff]</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7"><span style="color: #dfdfe0;">head</span>
</div><div class="line" data-line="8"><span style="color: #738091;"># &quot;a&quot;</span>
</div><div class="line" data-line="9">
</div><div class="line" data-line="10"><span style="color: #dfdfe0;">tail</span>
</div><div class="line" data-line="11"><span style="color: #738091;"># [&quot;list&quot;, :of, :stuff]</span>
</div></code></pre>
<p>Here we bound <code>b</code> to a list of 4 elements. Then we pattern-matched <code>b</code> against the pattern <code>[head | tail]</code>. Lists in Erlang (and consequently in Elixir) are like LISP lists, they're composed of cons cells, that can be thought of as a group of cells, where each cell holds a value and also a &quot;pointer&quot; to the next cell in the list.</p>
<p>In this case we can think of it as a structure where the first &quot;cell&quot; is <code>&quot;a&quot;</code>, which points to the cell with value <code>&quot;list&quot;</code>, which in turn points to the cell <code>:of</code>, which points to cell <code>:stuff</code> which in turn points to the end of the list (an empty list, <code>[]</code>).</p>
<p>So a list is a collection of cells where each element holds its value and points to the next element, that's why they're called <code>cons cells</code> and usually described as <code>(x . points_to_y)(y . points_to_z)(z . points_to_empty_list)()</code>, or more correctly <code>(x . (y . (z . ())))</code>. In Elixir and Erlang it looks like <code>[x | [y | [z | []]]]</code>.</p>
<p>So when we match <code>b</code> to the pattern <code>[head | tail]</code> what we're actually saying is, does a pattern of a non empty list (meaning where there is at least one cell, the <code>head</code>) match <code>b</code>? If it does,  bind the value of the first cell of that list to the variable <code>head</code> and the remaining of the list to the variable <code>tail</code>.</p>
<p>If we try:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #dfdfe0;">c</span> <span style="color: #aeafb0;">=</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="2"><span style="color: #738091;"># []</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4"><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">head</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">tail</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">c</span>
</div><div class="line" data-line="5"><span style="color: #738091;"># ** (MatchError) no match of right hand side value: []</span>
</div></code></pre>
<p>We get a match error, in this case we're trying to match a non-empty list (the pattern we wrote specifies it should have one element at least, <code>head</code>, pointing to a tail), against an empty list (<code>c</code>) so we get a match error, because an empty list has no cells, it's itself the end of the list. This contrasts with the previous seen case of the map, where the empty map <code>%&lbrace;&rbrace;</code> still matched ok, but in practical (and theoretical) terms it makes sense, once you start using it you'll see that the difference between what meaning an empty list and an empty map usually assume and the ability to match on simply being a <code>map</code> warrant this (seemingly) small contradiction. Also, if a match with <code>%&lbrace;&rbrace;</code> equated to saying an empty map, then when you were matching non-empty maps you would need to spell out all the keys in the map and that effectively and that completely defeats the pragmatic purpose of matches - or you would need to specify different behaviour for when using the pattern <code>%&lbrace;&rbrace;</code>.</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #dfdfe0;">d</span> <span style="color: #aeafb0;">=</span> <span style="color: #aeafb0;">[</span><span style="color: #81b29a;">&quot;non_empty&quot;</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="2"><span style="color: #738091;"># [&quot;non_empty&quot;]</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4"><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">head</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">tail</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">d</span>
</div><div class="line" data-line="5"><span style="color: #738091;"># [&quot;non_empty&quot;]</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7"><span style="color: #dfdfe0;">head</span>
</div><div class="line" data-line="8"><span style="color: #738091;"># &quot;non_empty&quot;</span>
</div><div class="line" data-line="9">
</div><div class="line" data-line="10"><span style="color: #dfdfe0;">tail</span>
</div><div class="line" data-line="11"><span style="color: #738091;"># []</span>
</div></code></pre>
<p>In this case though, we bound a list with one cell, <code>&quot;non_empty&quot;</code> to <code>d</code> and when we pattern matched, it worked. <code>&quot;non_empty&quot;</code> got bound to <code>head</code> and the end of the list (an empty list) got bound to <code>tail</code>.</p>
<p>Again, it's not super impressive (yet) but we'll get there soon.
Let's see one more example before though:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #dfdfe0;">deep</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">list_key: </span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:a_list</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">super_deep: </span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:a</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">date: </span><span style="color: #81b29a;">&quot;2019-05-01&quot;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="2"><span style="color: #738091;"># %&lbrace;date: &quot;2019-05-01&quot;, list_key: [:a_list, %&lbrace;super_deep: [:a]&rbrace;]&rbrace;</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4"><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">date: </span><span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">year</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">-</span><span style="color: #86abdc;">size</span><span style="color: #aeafb0;">(</span><span style="color: #f4a261;">4</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;-&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">month</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">-</span><span style="color: #86abdc;">size</span><span style="color: #aeafb0;">(</span><span style="color: #f4a261;">2</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;-&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">day</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">-</span><span style="color: #86abdc;">size</span><span style="color: #aeafb0;">(</span><span style="color: #f4a261;">2</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">list_key: </span><span style="color: #aeafb0;">[</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">super_deep: </span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">first_element_of_super_deep</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="5"><span style="color: #738091;"># %&lbrace;date: &quot;2019-05-01&quot;, list_key: [:a_list, %&lbrace;super_deep: [:a]&rbrace;]&rbrace;</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7"><span style="color: #aeafb0;">&gt;</span> <span style="color: #dfdfe0;">year</span>
</div><div class="line" data-line="8"><span style="color: #738091;"># &quot;2019&quot;</span>
</div><div class="line" data-line="9"><span style="color: #aeafb0;">&gt;</span> <span style="color: #dfdfe0;">month</span>
</div><div class="line" data-line="10"><span style="color: #738091;"># &quot;05&quot;</span>
</div><div class="line" data-line="11"><span style="color: #aeafb0;">&gt;</span> <span style="color: #dfdfe0;">day</span>
</div><div class="line" data-line="12"><span style="color: #738091;"># &quot;01&quot;</span>
</div><div class="line" data-line="13"><span style="color: #aeafb0;">&gt;</span> <span style="color: #dfdfe0;">first_element_of_super_deep</span>
</div><div class="line" data-line="14"><span style="color: #738091;"># :a</span>
</div></code></pre>
<p>Wow. So with a simple pattern matching, we were able to extract a lot of information as you can see. We didn't need to split a string to get all the pieces of the date, we didn't need to iterate on the list to get it's nested elements and we plucked an element from inside a list, that was inside a map, that was inside another list itself inside another map. We can also write it in a way that is more readable</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="2">    <span style="color: #86abdc;">date: </span><span style="color: #aeafb0;">&lt;&lt;</span>
</div><div class="line" data-line="3">        <span style="color: #dfdfe0;">year</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">-</span><span style="color: #86abdc;">size</span><span style="color: #aeafb0;">(</span><span style="color: #f4a261;">4</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="4">        <span style="color: #81b29a;">&quot;-&quot;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="5">        <span style="color: #dfdfe0;">month</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">-</span><span style="color: #86abdc;">size</span><span style="color: #aeafb0;">(</span><span style="color: #f4a261;">2</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="6">        <span style="color: #81b29a;">&quot;-&quot;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="7">        <span style="color: #dfdfe0;">day</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">-</span><span style="color: #86abdc;">size</span><span style="color: #aeafb0;">(</span><span style="color: #f4a261;">2</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="8">    <span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="9">    <span style="color: #86abdc;">list_key: </span><span style="color: #aeafb0;">[</span>
</div><div class="line" data-line="10">        <span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="11">        <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span>
</div><div class="line" data-line="12">            <span style="color: #86abdc;">this_will_fail: </span><span style="color: #aeafb0;">[</span>
</div><div class="line" data-line="13">                <span style="color: #dfdfe0;">first_element_of_super_deep</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">t</span>
</div><div class="line" data-line="14">            <span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="15">        <span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="16">    <span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="17"><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">deep</span>
</div><div class="line" data-line="18">
</div><div class="line" data-line="19"><span style="color: #738091;"># ** (MatchError) no match of right hand side value: %&lbrace;date: &quot;2019-05-01&quot;, list_key: [:a_list, %&lbrace;super_deep: [:a]&rbrace;]&rbrace;</span>
</div></code></pre>
<p>Here, in the pattern we described, we changed the key name inside the map inside the nested list to <code>this_will_fail</code> and it no longer matched, although everything else was the same as before.</p>
<p>So, this is a bit more impressive, although, still doesn't look very useful if we can only use this on match operations. Where it becomes really, really, useful is when we use it in conjunction with Elixir's (Erlang) ability to have multiple function definitions and/or inside some constructs the language provides, such as <code>case</code> statements (Well actually, most places, to be sincere, allow their usage).</p>
<p>You might also have noticed that we used <code>_</code> in these last pattern matches. <code>_</code> (or any variable name starting with <code>_</code>) tells the compiler we're not interested in that value, so it won't bind that variable, although it still requires something to be there.</p>
<p>So let's look at patterns with <code>case</code> statements, since they're very common too.</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #dfdfe0;">a</span> <span style="color: #aeafb0;">=</span> <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:a</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:list</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="2"><span style="color: #738091;"># [:a, :list]</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4"><span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">a</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="5">    <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:a</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:list</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;a list with :a and :list&quot;</span>
</div><div class="line" data-line="6">    <span style="color: #738091;">_</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;something else&quot;</span>
</div><div class="line" data-line="7"><span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="8"><span style="color: #738091;"># &quot;a list with :a and :list&quot;</span>
</div><div class="line" data-line="9">
</div><div class="line" data-line="10"><span style="color: #dfdfe0;">a</span> <span style="color: #aeafb0;">=</span> <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:b</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:list</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="11"><span style="color: #738091;"># [:b, :list]</span>
</div><div class="line" data-line="12">
</div><div class="line" data-line="13"><span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">a</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="14">    <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:a</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:list</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;a list with :a and :list&quot;</span>
</div><div class="line" data-line="15">    <span style="color: #738091;">_</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;something else&quot;</span>
</div><div class="line" data-line="16"><span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="17"><span style="color: #738091;"># &quot;something else&quot;</span>
</div><div class="line" data-line="18">
</div><div class="line" data-line="19"><span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">a</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="20">    <span style="color: #aeafb0;">[</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:list</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;a two element list where the second element is :list&quot;</span>
</div><div class="line" data-line="21">    <span style="color: #738091;">_</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;something else&quot;</span>
</div><div class="line" data-line="22"><span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="23"><span style="color: #738091;"># &quot;a two element list where the second element is :list&quot;</span>
</div><div class="line" data-line="24">
</div><div class="line" data-line="25"><span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">a</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="26">    <span style="color: #aeafb0;">[</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:list</span> <span style="color: #aeafb0;">|</span> <span style="color: #738091;">_t</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;a list with at least two elements where the second element is :list&quot;</span>
</div><div class="line" data-line="27">    <span style="color: #738091;">_</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;something else&quot;</span>
</div><div class="line" data-line="28"><span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="29"><span style="color: #738091;"># &quot;a list with at least two elements where the second element is :list&quot;</span>
</div><div class="line" data-line="30">
</div><div class="line" data-line="31"><span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">a</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="32">    <span style="color: #aeafb0;">[</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;a list with a single element&quot;</span>
</div><div class="line" data-line="33">    <span style="color: #aeafb0;">[</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;a list with 2 elements&quot;</span>
</div><div class="line" data-line="34">    <span style="color: #738091;">_</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;something else&quot;</span>
</div><div class="line" data-line="35"><span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="36"><span style="color: #738091;"># &quot;a list with 2 elements&quot;</span>
</div><div class="line" data-line="37">
</div><div class="line" data-line="38"><span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">a</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="39">    <span style="color: #aeafb0;">[</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;a list with a single element&quot;</span>
</div><div class="line" data-line="40">    <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:b</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:something_else</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;a list with 2 elements, :b and :something else&quot;</span>
</div><div class="line" data-line="41">    <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:b</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:list</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">tail</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;a list with 2 elements and a tail&quot;</span>
</div><div class="line" data-line="42"><span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="43"><span style="color: #738091;"># &quot;a list with 2 elements and a tail&quot;</span>
</div><div class="line" data-line="44">
</div><div class="line" data-line="45"><span style="color: #dfdfe0;">tail</span>
</div><div class="line" data-line="46"><span style="color: #738091;"># []</span>
</div></code></pre>
<p>Since lists are made of cons cells, this matched on the last branch, because although we only had 2 elements in the list it technically is 3, since a proper list always ends in an empty list itself. So by having a list with 2 elements what we actually have is:</p>
<p><code>(element_1 . points_to_element_2)(element_2 . points_to_end_of_list)() &lt;- this last element is itself an empty list.</code></p>
<p>If we did this, on the other hand:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">a</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">    <span style="color: #aeafb0;">[</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;a list with a single element&quot;</span>
</div><div class="line" data-line="3">    <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:b</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:something_else</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;a list with 2 elements&quot;</span>
</div><div class="line" data-line="4">    <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:b</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:list</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_last_element</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;a list with 3 elements&quot;</span>
</div><div class="line" data-line="5"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>We get instead:
<code>** (CaseClauseError) no case clause matching: [:b, :list]</code></p>
<p>So although the last element is present, given that it is the list termination (empty list) it doesn't count as an &quot;actual&quot; element, but just as the termination of the list. Notice that instead of separating the last element with <code>|</code> like we did previously, we separated it with a <code>,</code> (comma), effectively indicating our pattern required 3 actual elements, and not 2 elements and a tail.
Because the empty list that signals the end of a list is not itself an &quot;element&quot; it didn't match, but when we use <code>|</code> it does match, because the tail might be a cons cell or the end of the list itself - the <code>|</code> separator means the &quot;next pointer&quot; of the list, while <code>,</code> means an actual element.</p>
<p>We also see that because no branch of the case could match, that we got a <code>CaseClauseError</code>, which just means, given the expression passed on to <code>case</code>, I couldn't find any &quot;conforming&quot; branch in those you've defined.</p>
<p>As you see the logic is the same as with the match operator we've seen before, but instead of getting <code>MatchError</code>s when it doesn't match we get <code>CaseClauseError</code>s.</p>
<p>What happens when we use <code>case</code> is that the expression in <code>case EXPRESSION do</code> gets matched against each branch of the case statement, so it's translated into something similar to (for illustration purposes):</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #738091;"># when `a` is [:b, :list]</span>
</div><div class="line" data-line="2"><span style="color: #aeafb0;">&gt;</span> <span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">a</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="3"><span style="color: #aeafb0;">&gt;</span>&gt;   <span style="color: #aeafb0;">[</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">=</span> <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:b</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:list</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #dfdfe0;">...</span><span style="color: #aeafb0;">.</span>
</div><div class="line" data-line="4"><span style="color: #aeafb0;">&gt;</span><span style="color: #aeafb0;">&gt;</span>   <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:b</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:something_else</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">=</span> <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:b</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:list</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">-</span><span style="color: #aeafb0;">&gt;</span> <span style="color: #dfdfe0;">...</span>
</div><div class="line" data-line="5"><span style="color: #aeafb0;">&gt;</span>&gt;   <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:b</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:list</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">tail</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">=</span> <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:b</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:list</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">-</span><span style="color: #aeafb0;">&gt;</span> <span style="color: #dfdfe0;">...</span>
</div><div class="line" data-line="6"><span style="color: #aeafb0;">&gt;</span> <span style="color: #dfdfe0;">end</span>
</div></code></pre>
<p>So the first branch <code>[_]</code> (list with a single element) doesn't match, neither does the second branch <code>[:b, :something_else]</code>, but the third does, because <code>a</code> is effectively in the form <code>[:b | [:list | []]]</code>. Or <code>[:b, :list | []]</code></p>
<p>We can see some more examples, now with binary matching.</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #dfdfe0;">date</span> <span style="color: #aeafb0;">=</span> <span style="color: #81b29a;">&quot;01-02-2019&quot;</span>
</div><div class="line" data-line="2"><span style="color: #738091;"># &quot;01-02-2019&quot;</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4"><span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">date</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="5">    <span style="color: #81b29a;">&quot;01-02-&quot;</span> <span style="color: #aeafb0;">&lt;&gt;</span> <span style="color: #dfdfe0;">year</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;it&#39;s year </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #dfdfe0;">year</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span>
</div><div class="line" data-line="6">    <span style="color: #738091;">_</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;not sure&quot;</span>
</div><div class="line" data-line="7"><span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="8"><span style="color: #738091;"># &quot;it&#39;s year 2019&quot;</span>
</div><div class="line" data-line="9">
</div><div class="line" data-line="10"><span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">date</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="11">    <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">day</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">-</span><span style="color: #86abdc;">size</span><span style="color: #aeafb0;">(</span><span style="color: #f4a261;">3</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">month</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">-</span><span style="color: #86abdc;">size</span><span style="color: #aeafb0;">(</span><span style="color: #f4a261;">3</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">year</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">-</span><span style="color: #86abdc;">size</span><span style="color: #aeafb0;">(</span><span style="color: #f4a261;">4</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&gt;&gt;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;it&#39;s day </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #dfdfe0;">day</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;"> in month </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #dfdfe0;">month</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;"> and year </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #dfdfe0;">year</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span>
</div><div class="line" data-line="12">    <span style="color: #738091;">_</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;don&#39;t know&quot;</span>
</div><div class="line" data-line="13"><span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="14"><span style="color: #738091;"># &quot;it&#39;s day 01- in month 02- and year 2019&quot;</span>
</div><div class="line" data-line="15">
</div><div class="line" data-line="16"><span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">date</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="17">    <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">day</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">-</span><span style="color: #86abdc;">size</span><span style="color: #aeafb0;">(</span><span style="color: #f4a261;">2</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;-&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">month</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">-</span><span style="color: #86abdc;">size</span><span style="color: #aeafb0;">(</span><span style="color: #f4a261;">2</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;-&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">year</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">-</span><span style="color: #86abdc;">size</span><span style="color: #aeafb0;">(</span><span style="color: #f4a261;">4</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&gt;&gt;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;it&#39;s day </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #dfdfe0;">day</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;"> in month </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #dfdfe0;">month</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;"> and year </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #dfdfe0;">year</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span>
</div><div class="line" data-line="18">    <span style="color: #738091;">_</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;don&#39;t know&quot;</span>
</div><div class="line" data-line="19"><span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="20"><span style="color: #738091;"># &quot;it&#39;s day 01 in month 02 and year 2019&quot;</span>
</div><div class="line" data-line="21">
</div><div class="line" data-line="22"><span style="color: #dfdfe0;">date</span> <span style="color: #aeafb0;">=</span> <span style="color: #81b29a;">&quot;01/02/2019&quot;</span>
</div><div class="line" data-line="23"><span style="color: #738091;"># &quot;01/02/2019&quot;</span>
</div><div class="line" data-line="24">
</div><div class="line" data-line="25"><span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">date</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="26">    <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #dfdfe0;">day</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">-</span><span style="color: #86abdc;">size</span><span style="color: #aeafb0;">(</span><span style="color: #f4a261;">2</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;-&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">month</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">-</span><span style="color: #86abdc;">size</span><span style="color: #aeafb0;">(</span><span style="color: #f4a261;">2</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;-&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">year</span><span style="color: #aeafb0;">::</span><span style="color: #dfdfe0;">binary</span><span style="color: #aeafb0;">-</span><span style="color: #86abdc;">size</span><span style="color: #aeafb0;">(</span><span style="color: #f4a261;">4</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">&gt;&gt;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;it&#39;s day </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #dfdfe0;">day</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;"> in month </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #dfdfe0;">month</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;"> and year </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #dfdfe0;">year</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span>
</div><div class="line" data-line="27">    <span style="color: #738091;">_</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;don&#39;t know&quot;</span>
</div><div class="line" data-line="28"><span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="29"><span style="color: #738091;"># &quot;don&#39;t know&quot;</span>
</div></code></pre>
<p>So this is way more interesting, because now we can start seeing ways to drive the &quot;flow&quot; of our programs by defining the form the data should have.</p>
<p>When we look at functions, all the same concepts apply, but instead of being inside the body of a function, they're used to define what &quot;branch&quot; of the function should be &quot;called&quot; when passed arguments of a certain form.</p>
<p>Let's create a file somewhere. The following examples will all need to be placed inside that module but we'll omit it in the examples, and then the whole module must be copied to your iex shell before running the examples.</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #738091;"># some_file.ex</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">PatternMatching</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="4">
</div><div class="line" data-line="5">    <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">test_1</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:a</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #81b29a;">&quot;Function matched on :a&quot;</span>
</div><div class="line" data-line="6">    <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">test_1</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #81b29a;">&quot;Function matched on empty list&quot;</span>
</div><div class="line" data-line="7">    <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">test_1</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">element</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="8">        <span style="color: #7ad5d6;">IO</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">puts</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;Function matched on list with a single element: </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span> <span style="color: #dfdfe0;">element</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="9">        <span style="color: #86abdc;">test_1</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">element</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="10">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="11">    <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">test_1</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">head</span><span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="12">        <span style="color: #7ad5d6;">IO</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">puts</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;Function matched on non_empty list, with head: </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span> <span style="color: #dfdfe0;">head</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;"> and tail </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span> <span style="color: #dfdfe0;">tail</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="13">        <span style="color: #86abdc;">test_1</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="14">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="15">
</div><div class="line" data-line="16">    <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">test_1</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">element</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #81b29a;">&quot;Function with one non-list argument: </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span> <span style="color: #dfdfe0;">element</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span>
</div><div class="line" data-line="17">
</div><div class="line" data-line="18"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>Copy that into the iex shell and you should see something like:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #738091;"># &lbrace;:module, PatternMatching,</span>
</div><div class="line" data-line="2"> <span style="color: #aeafb0;">&lt;&lt;</span><span style="color: #f4a261;">70</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">79</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">82</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">49</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">0</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">0</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">7</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">128</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">66</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">69</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">65</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">77</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">65</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">116</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">85</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">56</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">0</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">0</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">0</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">189</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="3">   <span style="color: #f4a261;">0</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">0</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">0</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">20</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">22</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">69</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">108</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">105</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">120</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">105</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">114</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">46</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">80</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">97</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">116</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">116</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">101</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">114</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="4">   <span style="color: #f4a261;">110</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">77</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">97</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">116</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">99</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">104</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">105</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">110</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">103</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">...</span><span style="color: #aeafb0;">&gt;&gt;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">:test_1</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">1</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">&rbrace;</span>
</div></code></pre>
<p>Now let's try calling some functions:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #7ad5d6;">PatternMatching</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">test_1</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:a</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="2"><span style="color: #738091;"># &quot;Function matched on :a&quot;</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4"><span style="color: #7ad5d6;">PatternMatching</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">test_1</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:b</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="5"><span style="color: #738091;"># &quot;Function with one non-list argument: :b&quot;</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7"><span style="color: #7ad5d6;">PatternMatching</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">test_1</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:b</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="8"><span style="color: #738091;"># Function matched on list with a single element: :b</span>
</div><div class="line" data-line="9"><span style="color: #738091;"># &quot;Function with one non-list argument: :b&quot;</span>
</div><div class="line" data-line="10">
</div><div class="line" data-line="11"><span style="color: #7ad5d6;">PatternMatching</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">test_1</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:a</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="12"><span style="color: #738091;"># Function matched on list with a single element: :a</span>
</div><div class="line" data-line="13"><span style="color: #738091;"># &quot;Function matched on :a&quot;</span>
</div><div class="line" data-line="14">
</div><div class="line" data-line="15"><span style="color: #7ad5d6;">PatternMatching</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">test_1</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:b</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:b</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="16"><span style="color: #738091;"># Function matched on non_empty list, with head: :b and tail [:b]</span>
</div><div class="line" data-line="17"><span style="color: #738091;"># Function matched on list with a single element: :b</span>
</div><div class="line" data-line="18"><span style="color: #738091;"># &quot;Function with one non-list argument: :b&quot;</span>
</div></code></pre>
<p>Now if we move <code>def test_1(element), do: &quot;Function with one non-list argument: #&lbrace;inspect element&rbrace;&quot;</code>
to be the first function defined (and then copy the module again into iex) and run the same function calls we did before:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #7ad5d6;">PatternMatching</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">test_1</span><span style="color: #aeafb0;">(</span><span style="color: #86abdc;">:a</span><span style="color: #aeafb0;">)</span>                                                                            
</div><div class="line" data-line="2"><span style="color: #738091;"># &quot;Function with one non-list argument: :a&quot;</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4"><span style="color: #7ad5d6;">PatternMatching</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">test_1</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:b</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:a</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="5"><span style="color: #738091;"># &quot;Function with one non-list argument: [:b, :a]&quot;</span>
</div></code></pre>
<p>Now everything matches the first one, because it has no defined pattern it accepts everything so none of the other functions we defined get the chance to be tested and consequently run.</p>
<p>If we add this one function to the end:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">test_1</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">argument_1</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">argument_2</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #81b29a;">&quot;Matched with 2 arguments: 1: </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span> <span style="color: #dfdfe0;">argument_1</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;"> #### 2: </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span> <span style="color: #dfdfe0;">argument_2</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span>
</div></code></pre>
<p>Then copy the module again to iex and run:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #7ad5d6;">PatternMatching</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">test_1</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;arg1&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #81b29a;">&quot;arg&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;2&quot;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="2"><span style="color: #738091;"># &quot;Matched with 2 arguments: 1: \&quot;arg1\&quot; #### 2: [\&quot;arg\&quot;, \&quot;2\&quot;]&quot;</span>
</div></code></pre>
<p>Now because we're passing two actual arguments, none of the others will match (since they have arity of 1, meaning the number of arguments they accept is 1) and since only this last one accepts 2 arguments, only this one will match.</p>
<p>If we do:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #7ad5d6;">PatternMatching</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">test_1</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;arg1&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #81b29a;">&quot;arg&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;2&quot;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #81b29a;">&quot;arg3&quot;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="2"><span style="color: #738091;"># ** (UndefinedFunctionError) function PatternMatching.test_1/3 is undefined or private. Did you mean one of:</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4"><span style="color: #738091;">#      * test_1/1</span>
</div><div class="line" data-line="5"><span style="color: #738091;">#      * test_1/2</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7"><span style="color: #738091;">#    PatternMatching.test_1(&quot;arg1&quot;, [&quot;arg&quot;, &quot;2&quot;], &quot;arg3&quot;)</span>
</div></code></pre>
<p>This basically means, &quot;I'm sorry, I couldn't find a function test_1 with arity 3 in the module PatternMatching&quot;. It also hints, if it can find suitable hypotheses, other functions that are available in that module. In this case it can see that we have a function named &quot;test_1&quot; with both arity 1 and 2, so perhaps we might have tried to call that but got the arity wrong.</p>
<p>So by now we have seen some use cases for pattern matching and we've learned a bit about them, they will match the first case that has a conforming pattern, be it a branch of a <code>case</code> statement or a function definition.</p>
<p>This means, that the order in which we define the branches or functions has a meaning as well. And also that they will raise specific errors when it can't find an actionable code path.
If we define the branch or function as simply a bound (or unbound, <code>_</code>, variable) then it will match everything.</p>
<p>So our patterns must go from the most explicit to the least explicit in order to be unambiguous and actually describe the flow of our program.
In <code>case</code> statements, the whole expression is matched as a single element, while in functions there's also arity to take into account.</p>
<p>One last piece of functionality that we can use in pattern matching is guard clauses. These allow us to extend further our pattern matching capabilities. These guard clauses allow the usage of a subset of kernel functions that are &quot;special&quot;, in the sense that they are pure functions and guaranteed to be &quot;fast&quot;. So for instance we might want to discern if the value is a list or a map, if it's a map we also want to discern between an empty map and a non-empty map, but in the case of it being a list we don't care if it's a list with 0 or more elements, just that it's a list.
We could write it as such:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #dfdfe0;">a_list</span> <span style="color: #aeafb0;">=</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="2">
</div><div class="line" data-line="3"><span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">a_list</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="4">    <span style="color: #dfdfe0;">expression</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_list</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">expression</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;it&#39;s a list&quot;</span>
</div><div class="line" data-line="5">    <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">expression</span> <span style="color: #9d79d6;">when</span> <span style="color: #dfdfe0;">expression</span> <span style="color: #aeafb0;">==</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;it&#39;s an empty map&quot;</span>
</div><div class="line" data-line="6">    <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">expression</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;it&#39;s a non-empty map&quot;</span>
</div><div class="line" data-line="7"><span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="8">
</div><div class="line" data-line="9"><span style="color: #738091;"># &quot;it&#39;s a list&quot;</span>
</div><div class="line" data-line="10">
</div><div class="line" data-line="11">
</div><div class="line" data-line="12"><span style="color: #dfdfe0;">a_list</span> <span style="color: #aeafb0;">=</span> <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:two</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:elements</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="13">
</div><div class="line" data-line="14"><span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">a_list</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="15">    <span style="color: #dfdfe0;">expression</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_list</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">expression</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;it&#39;s a list&quot;</span>
</div><div class="line" data-line="16">    <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">expression</span> <span style="color: #9d79d6;">when</span> <span style="color: #dfdfe0;">expression</span> <span style="color: #aeafb0;">==</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;it&#39;s an empty map&quot;</span>
</div><div class="line" data-line="17">    <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">expression</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;it&#39;s a non-empty map&quot;</span>
</div><div class="line" data-line="18"><span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="19">
</div><div class="line" data-line="20"><span style="color: #738091;"># &quot;it&#39;s a list&quot;</span>
</div><div class="line" data-line="21">
</div><div class="line" data-line="22">
</div><div class="line" data-line="23"><span style="color: #dfdfe0;">a_list</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="24"><span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">a_list</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="25">    <span style="color: #dfdfe0;">expression</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_list</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">expression</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;it&#39;s a list&quot;</span>
</div><div class="line" data-line="26">    <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">expression</span> <span style="color: #9d79d6;">when</span> <span style="color: #dfdfe0;">expression</span> <span style="color: #aeafb0;">==</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;it&#39;s an empty map&quot;</span>
</div><div class="line" data-line="27">    <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">expression</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;it&#39;s a non-empty map&quot;</span>
</div><div class="line" data-line="28"><span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="29">
</div><div class="line" data-line="30"><span style="color: #738091;"># &quot;it&#39;s an empty map&quot;</span>
</div><div class="line" data-line="31">
</div><div class="line" data-line="32"><span style="color: #dfdfe0;">a_list</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">some_key: </span><span style="color: #f4a261;">1</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="33"><span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">a_list</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="34">    <span style="color: #dfdfe0;">expression</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_list</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">expression</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;it&#39;s a list&quot;</span>
</div><div class="line" data-line="35">    <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">expression</span> <span style="color: #9d79d6;">when</span> <span style="color: #dfdfe0;">expression</span> <span style="color: #aeafb0;">==</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;it&#39;s an empty map&quot;</span>
</div><div class="line" data-line="36">    <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">expression</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;it&#39;s a non-empty map&quot;</span>
</div><div class="line" data-line="37"><span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="38">
</div><div class="line" data-line="39"><span style="color: #738091;"># &quot;it&#39;s a non-empty map&quot;</span>
</div><div class="line" data-line="40">
</div><div class="line" data-line="41"><span style="color: #7ad5d6;">If</span> we <span style="color: #86abdc;">switch</span> <span style="color: #86abdc;">the</span> <span style="color: #86abdc;">last</span> <span style="color: #86abdc;">two</span> <span style="color: #dfdfe0;">branches</span> <span style="color: #aeafb0;">and</span> <span style="color: #86abdc;">set</span> `<span style="color: #86abdc;">a_list</span>` <span style="color: #86abdc;">variable</span> <span style="color: #86abdc;">to</span> <span style="color: #86abdc;">an</span> <span style="color: #86abdc;">empty</span> <span style="color: #86abdc;">map</span> <span style="color: #86abdc;">we</span> <span style="color: #86abdc;">get:
</div><div class="line" data-line="42"></span>
</div><div class="line" data-line="43"><span style="color: #dfdfe0;">a_list</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="44"><span style="color: #9d79d6;">case</span> <span style="color: #dfdfe0;">a_list</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="45">    <span style="color: #dfdfe0;">expression</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_list</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">expression</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;it&#39;s a list&quot;</span>
</div><div class="line" data-line="46">    <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">expression</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;it&#39;s a non-empty map </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">inspect</span> <span style="color: #dfdfe0;">expression</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;">&quot;</span>
</div><div class="line" data-line="47">    <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">expression</span> <span style="color: #9d79d6;">when</span> <span style="color: #dfdfe0;">expression</span> <span style="color: #aeafb0;">==</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #81b29a;">&quot;it&#39;s an empty map&quot;</span>
</div><div class="line" data-line="48"><span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="49">
</div><div class="line" data-line="50"><span style="color: #738091;"># &quot;it&#39;s a non-empty map %&lbrace;&rbrace;&quot;</span>
</div></code></pre>
<p>Although the map is empty, because the 2nd branch matches any map, empty or not, it's that one that gets evaluated when the expression is a map, and the 3rd branch now has no chance to be tested.</p>
<p>So now let's see some real cases where we can use this.</p>
<p>Let's define a module and structure that holds users and the type of users they are along with their age. We'll also define some functions to work with lists of users.</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">defmodule</span> <span style="color: #7ad5d6;">User</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">	<span style="color: #9d79d6;">defstruct</span> <span style="color: #aeafb0;">[</span><span style="color: #86abdc;">:name</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:age</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">type: </span><span style="color: #86abdc;">:regular</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="3">
</div><div class="line" data-line="4">    <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">count_older_than</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">list</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">age</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="5">        <span style="color: #86abdc;">count_older_than</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">list</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">age</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">0</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="6">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="7">
</div><div class="line" data-line="8">    <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">count_older_than</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">count</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #dfdfe0;">count</span>
</div><div class="line" data-line="9">
</div><div class="line" data-line="10">    <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">count_older_than</span><span style="color: #aeafb0;">(</span>
</div><div class="line" data-line="11">        <span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">age: </span><span style="color: #dfdfe0;">user_age</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">user</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="12">        <span style="color: #dfdfe0;">age</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="13">        <span style="color: #dfdfe0;">count</span>
</div><div class="line" data-line="14">    <span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #dfdfe0;">user_age</span> <span style="color: #aeafb0;">&gt;</span> <span style="color: #dfdfe0;">age</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="15">        <span style="color: #86abdc;">count_older_than</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">age</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">count</span> <span style="color: #aeafb0;">+</span> <span style="color: #f4a261;">1</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="16">    <span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="17">
</div><div class="line" data-line="18">    <span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">count_older_than</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">[</span><span style="color: #738091;">_</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">age</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">count_older_than</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">age</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="19"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>And now let's create some users and a list of them:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #dfdfe0;">user_1</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;John&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">age: </span><span style="color: #f4a261;">25</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="2"><span style="color: #dfdfe0;">user_2</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;Doris&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">age: </span><span style="color: #f4a261;">30</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">type: </span><span style="color: #86abdc;">:administrator</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="3"><span style="color: #dfdfe0;">user_3</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;Jane&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">age: </span><span style="color: #f4a261;">28</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="4"><span style="color: #dfdfe0;">user_4</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;Joe&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">age: </span><span style="color: #f4a261;">60</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">type: </span><span style="color: #86abdc;">:administrator</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="5"><span style="color: #dfdfe0;">user_5</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;Jelly&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">age: </span><span style="color: #f4a261;">15</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7"><span style="color: #dfdfe0;">list_of_users</span> <span style="color: #aeafb0;">=</span> <span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">user_1</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">user_2</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">user_3</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">user_4</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">user_5</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="8"><span style="color: #738091;"># [</span>
</div><div class="line" data-line="9"><span style="color: #738091;">#   %User&lbrace;age: 25, name: &quot;John&quot;, type: :regular&rbrace;,</span>
</div><div class="line" data-line="10"><span style="color: #738091;">#   %User&lbrace;age: 30, name: &quot;Doris&quot;, type: :administrator&rbrace;,</span>
</div><div class="line" data-line="11"><span style="color: #738091;">#   %User&lbrace;age: 28, name: &quot;Jane&quot;, type: :regular&rbrace;,</span>
</div><div class="line" data-line="12"><span style="color: #738091;">#   %User&lbrace;age: 60, name: &quot;Joe&quot;, type: :administrator&rbrace;,</span>
</div><div class="line" data-line="13"><span style="color: #738091;">#    %User&lbrace;name: &quot;Jelly&quot;, age: 15, type: :regular&rbrace;</span>
</div><div class="line" data-line="14"><span style="color: #738091;"># ]</span>
</div><div class="line" data-line="15">
</div><div class="line" data-line="16"><span style="color: #dfdfe0;">count</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">count_older_than</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">list_of_users</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">28</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="17"><span style="color: #738091;"># 2</span>
</div><div class="line" data-line="18">
</div><div class="line" data-line="19"><span style="color: #dfdfe0;">count</span>
</div><div class="line" data-line="20"><span style="color: #738091;"># 2</span>
</div><div class="line" data-line="21">
</div><div class="line" data-line="22"><span style="color: #dfdfe0;">count</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">count_older_than</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">list_of_users</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">25</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="23"><span style="color: #738091;"># 3</span>
</div><div class="line" data-line="24">
</div><div class="line" data-line="25"><span style="color: #dfdfe0;">count</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">count_older_than</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">list_of_users</span><span style="color: #aeafb0;">,</span> <span style="color: #f4a261;">20</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="26"><span style="color: #738091;"># 4</span>
</div></code></pre>
<p>Now lets add these functions to the previous module and copy it again to iex:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">extract_administrators</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">list</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_list</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">list</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">    <span style="color: #86abdc;">extract_administrators</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">list</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="3"><span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="4">
</div><div class="line" data-line="5"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">extract_administrators</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #dfdfe0;">acc</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">extract_administrators</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">type: </span><span style="color: #86abdc;">:administrator</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">user</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="8">    <span style="color: #86abdc;">extract_administrators</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">user</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="9"><span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="10"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">extract_administrators</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">[</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">extract_administrators</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span>
</div></code></pre>
<p>And then run</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #dfdfe0;">admins</span> <span style="color: #aeafb0;">=</span> <span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">extract_administrators</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">list_of_users</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="2"><span style="color: #738091;"># [</span>
</div><div class="line" data-line="3"><span style="color: #738091;">#   %User&lbrace;age: 60, name: &quot;Joe&quot;, type: :administrator&rbrace;,</span>
</div><div class="line" data-line="4"><span style="color: #738091;">#   %User&lbrace;age: 30, name: &quot;Doris&quot;, type: :administrator&rbrace;</span>
</div><div class="line" data-line="5"><span style="color: #738091;"># ]</span>
</div></code></pre>
<p>So you can see that we called first the <code>extract_administrators</code> with only 1 argument, a list, so it matched the first function definition. This function all it did was call the same function, but now with two arguments, the second being an empty list.</p>
<p>This is a fairly regular thing to do, that 2nd argument (in this case) is what is usually called the &quot;accumulator&quot; and it's a simple way of recursively calling functions and &quot;accumulate&quot; the results of each call. In this case it's used to build a new list with all the administrators we find in the original list.</p>
<p>So this call ends up as (given the list we were working with):</p>
<p><code>extract_administrators([%User&lbrace;name: &quot;John&quot;, age: 25, type: :regular&rbrace; | t], [])</code></p>
<p>Given that the first argument is not an empty list, it can't match the second function declaration. Given that the first cell in the first argument list is not a <code>%User&lbrace;&rbrace;</code> struct with the type <code>:administrator</code> it can't match the 3rd function, so it matches the 4th function:</p>
<p><code>def extract_administrators([_| t], acc), do: extract_administrators(t, acc)</code></p>
<p>In this function, what happens is, we ignore that first value, and we're only interested in the remaining list.</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">age: </span><span style="color: #f4a261;">25</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;John&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">type: </span><span style="color: #86abdc;">:regular</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">|</span> <span style="color: #738091;">#head</span>
</div><div class="line" data-line="2">    <span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">age: </span><span style="color: #f4a261;">30</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;Doris&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">type: </span><span style="color: #86abdc;">:administrator</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">|</span> 
</div><div class="line" data-line="3">        <span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">age: </span><span style="color: #f4a261;">28</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;Jane&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">type: </span><span style="color: #86abdc;">:regular</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">|</span>
</div><div class="line" data-line="4">            <span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">age: </span><span style="color: #f4a261;">60</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;Joe&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">type: </span><span style="color: #86abdc;">:administrator</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">|</span>
</div><div class="line" data-line="5">                <span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;Jelly&quot;</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">age: </span><span style="color: #f4a261;">15</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">type: </span><span style="color: #86abdc;">:regular</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">|</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="6">            <span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="7">        <span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="8">    <span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="9"><span style="color: #aeafb0;">]</span>
</div></code></pre>
<p>So in this case we ignore <code>_</code> the head, and we call again the function <code>extract_administrators</code> with the remaining list and whatever is in the <code>acc</code> variable, so, which ends up being this call:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #86abdc;">extract_administrators</span><span style="color: #aeafb0;">(</span>
</div><div class="line" data-line="2">    <span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;Doris&quot;</span>...<span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">|</span> 
</div><div class="line" data-line="3">        <span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;Jane&quot;</span>...<span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">|</span>
</div><div class="line" data-line="4">            <span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;Joe&quot;</span>...<span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">|</span>
</div><div class="line" data-line="5">                <span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;Jelly&quot;</span>...<span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">|</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="6">            <span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="7">        <span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="8">    <span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div></code></pre>
<p>Now when this function is called with these new parameters it will actually match the 3rd function clause</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">extract_administrators</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">type: </span><span style="color: #86abdc;">:administrator</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">user</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">    <span style="color: #86abdc;">extract_administrators</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">user</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="3"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>So here what we do is bind <code>user</code> to the <code>element</code>, and then call the function again with its tail, while also adding the user into the accumulator in the last argument.</p>
<p>You can see that it's a bit of symmetric operation when the head matches our constraints/pattern, we take the <code>head</code> from one list, and we place that as the <code>head</code> of the accumulator, then we pass the <code>tail</code> of the list, from which we took the <code>head</code> from, as the new list to the function.</p>
<p>The first time, acc was empty,  <code>[]</code>
If we declare <code>[user | acc]</code> , what we're declaring is:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">...</span>.<span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">|</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">]</span>
</div></code></pre>
<p>If we do it again with another user</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">|</span> <span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">|</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">]</span>
</div></code></pre>
<p>And so on.</p>
<p>So now it will be called as:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #86abdc;">extract_administrators</span><span style="color: #aeafb0;">(</span>
</div><div class="line" data-line="2">    <span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;Jane&quot;</span>...<span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">|</span>
</div><div class="line" data-line="3">        <span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;Joe&quot;</span>...<span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">|</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="4">    <span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;Doris&quot;</span>...<span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div></code></pre>
<p>Which again will match only the 4th function clause.</p>
<p>So then it's called as:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #86abdc;">extract_administrators</span><span style="color: #aeafb0;">(</span>
</div><div class="line" data-line="2">    <span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;Joe&quot;</span>...<span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">|</span> 
</div><div class="line" data-line="3">        <span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;Jelly&quot;</span>...<span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">|</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="4">    <span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;Doris&quot;</span>...<span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">|</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div></code></pre>
<p>Which matches on the 3rd, so it will now call as:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #86abdc;">extract_administrators</span><span style="color: #aeafb0;">(</span>
</div><div class="line" data-line="2">    <span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;Jelly&quot;</span>...<span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">|</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span>
</div><div class="line" data-line="3">    <span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;Joe&quot;</span>...<span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">|</span> <span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;Doris&quot;</span>...<span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">|</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">)</span>
</div></code></pre>
<p>Which again matches only the forth it's called again this time with an empty list as the first argument.
And now because the first argument is empty, it matches on the 2nd function clause, where we end the recursion and just return the <code>acc</code> argument, leading to:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;Joe&quot;</span>...<span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #81b29a;">&quot;Doris&quot;</span>...<span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">]</span>
</div></code></pre>
<p>These are also composable, for instance you can use:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #dfdfe0;">list_of_users</span>
</div><div class="line" data-line="2"><span style="color: #aeafb0;">|&gt;</span> <span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">extract_administrators</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="3"><span style="color: #aeafb0;">|&gt;</span> <span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">count_older_than</span><span style="color: #aeafb0;">(</span><span style="color: #f4a261;">28</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="4"><span style="color: #738091;"># 2</span>
</div></code></pre>
<p>The last part of this write up is about using function clauses with different arities and pattern-matches in anonymous functions. There are a lot of modules in the standard lib that take functions as one of their parameters, specially those that deal with collections, such as the <code>Enum</code> module.</p>
<p>The <code>Enum</code> module has one function called <code>reduce/3</code> that basically is an abstraction over what we did we these functions. It takes an enumerable, an accumulator and a function, and we can use it to reduce the elements of the enumerable into whatever accumulator we want. We could write the <code>extract_administrators</code> function as:</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">extract_administrators</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">list</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_list</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">list</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">    <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">list</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span>
</div><div class="line" data-line="3">        <span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">type: </span><span style="color: #86abdc;">:administrator</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">user</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #aeafb0;">[</span><span style="color: #dfdfe0;">user</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">]</span>
</div><div class="line" data-line="4">        <span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #dfdfe0;">acc</span>
</div><div class="line" data-line="5">    <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="6"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>You can see two clauses on the <code>fn</code> declaration. <code>Enum.reduce</code> passes one element at a time from the <code>enumerable</code> provided as the first argument, to the anonymous function, along with the 2nd argument as the accumulator. The first time the anonymous function is called, the accumulator is the original accumulator in the 2nd argument (an empty list), and on the following ones it's whatever the anonymous function returned.</p>
<p>Since we receive each element one by one (outside of their original list) we just pattern match on the element. When all elements from the enumerable have been <code>enumerated</code> it returns whatever is the value of the accumulator.</p>
<p>There are plenty of use cases for recursive traversal of collections, in functional languages that's usually how you work on collections of items. There are also other useful functions in the <code>Enum</code> module. I use <code>reduce</code> and <code>map</code> a lot but there are more.</p>
<p>There's also other tricks you can use, such as using the same name for variables, underneath this makes the pattern only succeed if all instances of the binding resolve to the same value.</p>
<p>So for instance let's say you wanted to take pairs of users out of that list, that shared the same type of user.</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">pluck_pairs</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">list</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">when</span> <span style="color: #86abdc;">is_list</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">list</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">    <span style="color: #86abdc;">pluck_pair</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">list</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="3"><span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="4">
</div><div class="line" data-line="5"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">pluck_pairs</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">full_acc</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #dfdfe0;">full_acc</span>
</div><div class="line" data-line="6">
</div><div class="line" data-line="7"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">pluck_pairs</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">type: </span><span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">user</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="8">    <span style="color: #86abdc;">pluck_pairs</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">user</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="9"><span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="10">
</div><div class="line" data-line="11"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">pluck_pairs</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">[</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">type: </span><span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">user</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">previous</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="12">    <span style="color: #86abdc;">pluck_pairs</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">previous</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">user</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="13"><span style="color: #9d79d6;">end</span>
</div><div class="line" data-line="14">
</div><div class="line" data-line="15">
</div><div class="line" data-line="16"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">pluck_pairs</span><span style="color: #aeafb0;">(</span><span style="color: #aeafb0;">[</span><span style="color: #738091;">_</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">do: </span><span style="color: #86abdc;">pluck_pairs</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">t</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span>
</div></code></pre>
<p>Or using the <code>Enum.reduce</code> form</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">def</span> <span style="color: #86abdc;">pluck_pairs</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">list_of_users</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">    <span style="color: #7ad5d6;">Enum</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">reduce</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">list_of_users</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">,</span> <span style="color: #9d79d6;">fn</span>
</div><div class="line" data-line="3">        <span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">type: </span><span style="color: #aeafb0;">^</span><span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">user</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">user</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="4">        <span style="color: #aeafb0;">(</span><span style="color: #7ad5d6;">%</span><span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">type: </span><span style="color: #aeafb0;">^</span><span style="color: #dfdfe0;">type</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">user</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">previous_match</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #aeafb0;">&lbrace;</span><span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #dfdfe0;">previous_match</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">user</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">|</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">]</span><span style="color: #aeafb0;">&rbrace;</span>
</div><div class="line" data-line="5">        <span style="color: #aeafb0;">(</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">full_acc</span><span style="color: #aeafb0;">)</span> <span style="color: #aeafb0;">-&gt;</span> <span style="color: #dfdfe0;">full_acc</span>
</div><div class="line" data-line="6">    <span style="color: #9d79d6;">end</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="7"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>(we need to use the <code>^</code> pin operator to pin down the value of <code>type</code>, otherwise it would be re-bound during the <code>Enum.reduce</code> and match anything)</p>
<p>Another thing to keep in mind is, if the order of the accumulation matters,  that after reducing a collection the accumulator will have the elements in the inverse order, so if that's relevant you need to reverse the list, like with <code>Enum.reverse/1</code> or the erlang <code>:lists.reverse/1</code> (if it's a lit obviously) function.</p>
<p>And now you could use this inside a case function</p>
<pre class="lumis" style="color: #cdcecf; background-color: #192330;"><code class="language-elixir" translate="no" tabindex="0"><div class="line" data-line="1"><span style="color: #9d79d6;">case</span> <span style="color: #7ad5d6;">User</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">pluck_pairs</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">list_of_users</span><span style="color: #aeafb0;">,</span> <span style="color: #86abdc;">:regular</span><span style="color: #aeafb0;">)</span> <span style="color: #9d79d6;">do</span>
</div><div class="line" data-line="2">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">|</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> 
</div><div class="line" data-line="3">        <span style="color: #7ad5d6;">IO</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">puts</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;No unmatched user and </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">length</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;"> matched pairs&quot;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="4">        <span style="color: #7ad5d6;">Notifications</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">send_pair_emails</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="5">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #dfdfe0;">name</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">no_pair</span><span style="color: #aeafb0;">,</span> <span style="color: #aeafb0;">[</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">|</span><span style="color: #738091;">_</span><span style="color: #aeafb0;">]</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="6">        <span style="color: #7ad5d6;">IO</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">puts</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;Unmatched user </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #dfdfe0;">name</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;"> and </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #86abdc;">length</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;"> matched pairs&quot;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="7">        <span style="color: #7ad5d6;">Notifications</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">send_no_pair_email</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">user</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="8">        <span style="color: #7ad5d6;">Notifications</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">send_pair_emails</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="9">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #7ad5d6;">%</span><span style="color: #aeafb0;">&lbrace;</span><span style="color: #86abdc;">name: </span><span style="color: #dfdfe0;">name</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">=</span> <span style="color: #dfdfe0;">user</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span> 
</div><div class="line" data-line="10">        <span style="color: #7ad5d6;">IO</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">puts</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;Unmatched user </span><span style="color: #86abdc;">#&lbrace;</span><span style="color: #dfdfe0;">name</span><span style="color: #86abdc;">&rbrace;</span><span style="color: #81b29a;"> and no pairs&quot;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="11">        <span style="color: #7ad5d6;">Notifications</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">send_no_pair_email</span><span style="color: #aeafb0;">(</span><span style="color: #dfdfe0;">user</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="12">        <span style="color: #dfdfe0;">acc</span>
</div><div class="line" data-line="13">    <span style="color: #aeafb0;">&lbrace;</span><span style="color: #f6b079;">nil</span><span style="color: #aeafb0;">,</span> <span style="color: #dfdfe0;">acc</span><span style="color: #aeafb0;">&rbrace;</span> <span style="color: #aeafb0;">-&gt;</span>
</div><div class="line" data-line="14">        <span style="color: #7ad5d6;">IO</span><span style="color: #aeafb0;">.</span><span style="color: #86abdc;">puts</span><span style="color: #aeafb0;">(</span><span style="color: #81b29a;">&quot;No pairs and no unmatched users&quot;</span><span style="color: #aeafb0;">)</span>
</div><div class="line" data-line="15">        <span style="color: #dfdfe0;">acc</span>
</div><div class="line" data-line="16"><span style="color: #9d79d6;">end</span>
</div></code></pre>
<p>And so on. Given the natural support for concurrent and parallel processes in Erlang &amp; Elixir, the usage of message passing and so on, pattern matching becomes even more useful, as it's fairly straightforward to describe state-machine'y behaviours using a combination of processes, receive blocks and pattern matching. Of course, most of that is already quite abstracted into higher OTP constructs such as gen_server, gen_statem and other friends.
Hope this post helped you understand better pattern matching and illustrated some use cases, although there's plenty more that can't simply be covered in detail here - nonetheless try out and experiment!</p> ]]></description>
    </item>
    <item>
       <title>Meditation Without Mambojambo</title>
       <link>https://micaelnussbaumer.com/meditation-without-mambojambo/</link>
       <pubDate>Thu, 08 Jun 2017 00:00:00 UTC</pubDate>
       <guid>https://micaelnussbaumer.com/meditation-without-mambojambo/</guid>
       <description><![CDATA[ <p>I also don't like much of the mambojambo that goes around many of the nowadays trends, but I'm an advocate of meditation. I'm going to try to explain why meditation is valuable in a plausible manner, without metaphysical properties.</p>
<p>I don't derive income on the topic, nor anything related - although I don't think there's a problem with selling your knowledge regarding this if you're doing it correctly and helping other people.</p>
<p>Even though I'm going to argue for analytical reasons, you should notice that most traditions aim to realise the &quot;Truth&quot; and answering the most fundamental questions of our existence and reality and in those realms that are highly spiritual we don't have, luckily or unluckily, a scientific language, so terms are used loosely (or everybody has their own definition so globally they become loosely defined, although in each one's definition they're very concise) to describe many things, sometimes not correctly. I'm also not going to argue for its &quot;health&quot; benefits, because sincerely, if you only care about health go to the gym.</p>
<p>Now bear with me, and you might find something worth taking your time thinking about.</p>
<p>How do you come to have the mind you have today?</p>
<p>By &quot;mind&quot; I mean what seats underneath your skin and from which you as a person sprout? Through your words, modes of being, actions, choices, options. This thing that controls these things, is what I'm calling &quot;mind&quot; here.</p>
<p>As your brain developed, even in the womb of your mother, it started being shaped. Experiences, nervous stimuli and others, experienced by your mother, are received as inputs and help structure your neuronal network and nervous system, even before you're out in the world. Which is nothing short than awe-inspiring by itself.</p>
<p>Later, already on the outside, the inputs you keep receiving (even those received in a time when you can't create memories out of them), &quot;print&quot; certain neuronal structures in your brain.</p>
<p>As you grow up, these structures are either re-enforced or not stimulated, and that makes them either grow bigger roots in your mind or wither away, pretty much like a tree in regards to being watered or not. Besides that, new structures get printed, or to say it more poetically a tree of neurons starts growing, with branches, leaves and all sorts of tree like things.</p>
<p>Now lets make a stop to consider what is a thought. So say for instance, you're afraid of dogs because when you were a child, you were bitten by one (I know it's a cliché, but exercise a bit of suspension of disbelief). This traumatic event created a structure in your mind right?</p>
<p>It printed some sensorial information, like a dog shaped thing, maybe the barking sound, maybe smell, maybe many other variables that were involved at the moment of the happening. You didn't specifically record &quot;that&quot; dog, because we humans don't do that, instead you recorded &quot;inputs&quot; that correlated to that experience but, since we humans also have language, you can symbolise these &quot;inputs&quot; and call them &quot;dog&quot;.</p>
<p>Any experience creates or organizes neurones in a certain pattern that reflect the experience, in the brain. So when faced with something that fires up one of the neurones (or many) linked to this experience, it creates a certain pattern of reaction in your mind, that trickles down from your mind, to your body, in the form of salivation, an alert, a flight or fight response, a panic attack, a smile, a burst of joy, god knows what. In the case you're scared of dogs, when you see or sense a dog you'll react accordingly.</p>
<p>This is also known as &quot;classical conditioning&quot; and the most famous example is probably the work of Pavlov, where by serving food to his dogs coupled with a non-related input (the sound of a bell, or a metronome) and repeating this action for a few times he got his dogs to salivate just by reproducing the sound, even when no food was being given. Why? Probably because the repetition created a pattern in the dog's brain, where the sound and the idea of food where interconnected so, when the sound was heard, it triggered the same reaction (salivation) as when food was given.</p>
<p>You see, a thought is nothing in itself, it's an arbitrary arrangement of neurones that encapsulate something external to our minds, in a way that we can relate to it and &quot;think&quot; it or &quot;experience&quot; it. It can also trigger other patterns and groups of neurones and make them fire.</p>
<p>Usually in our lives these &quot;thoughts&quot;, or patterns of neurones, are fired in specific situations. You can become &quot;aware&quot; of them, say for instance the dog situation but, in many others that aren't as clear as that, you might not.</p>
<p>In the case of the dog some people will say that, to overcome this irrational fear, you should try to spend some time with dogs that aren't aggressive. By doing this you are probably simply replacing by repetition a certain structure of neurones by another one. If you do it several times, when you face a dog instead of the experience activating the old traumatic events, it will activate these new made structures, that you created by spending time with them. So the &quot;input&quot; of an &quot;object&quot; that has the characteristics of a dog in your mind no longer fires the neurones, or the pattern of neurones, that would trickle a fight or flight response previously.</p>
<p>So this is cool right? It kinda means that you have the power to shape part of your reactions - you could even call it, the power to hack your own mind.</p>
<p>Now, like I said, most of our thoughts and reactions occur in specific situations but we aren't always aware of what actually triggers them. Some times because we are ourselves experiencing the situation, others because it's not always obvious to us, and yet others because we simply don't have the time to go through the sequence of experience in a detached manner (or we may not even be able to).</p>
<p>This is where meditation fits in.</p>
<p>When you start meditating, what gets fired in your head is at the &quot;surface&quot; of your conscious mind (you see, how can we talk scientifically about this shit really? surface of the mind? is that even a thing…).</p>
<p>Because you haven't trained your mind yet to have an anchor, all the electrical impulses firing through your beautiful scalp trigger all sorts of day-to-day thoughts that are in your mind and, if you're anything like other people, you can probably see that the thoughts towards which you're drifting are related to recent events or forth-coming events.</p>
<p>Once you begin to get a hold on how to re-focus your mind from this so said &quot;superficial&quot; thoughts, you begin to go a bit deeper in the machinations of your mind. But to be able to re-focus and sustain focus outside of the thought web you'll first need to practice. Sometimes it will seem pointless but I can assure you, as an over-thinker, that you'll eventually manage it, as long as you keep sitting in silence regularly.</p>
<p>At this level, it's a bit more subtle. Thoughts arise from random impulses in your mind. Where do thoughts come from when you have no external stimuli for them?</p>
<p>I would say that since your mind is always operating, what starts happening is that what gets fired inside your brain - I mean the patterns of neurones that get fired - are the patterns that are more &quot;vividly&quot; printed in your brain. (and they can be vivid both by intensity and intensity together with recent timing, the last usually fading away as time moves forward, since they stop being recent - like if yesterday you had something important on your mind it might pop up but after a week, or even next day if it's no longer relevant, it probably won't pop up again)</p>
<p>It makes sense no?</p>
<p>It's like you have a room full of air and an inflammable gas floating in it as well, in a relevant quantity. If you light a lighter in there - BAM! - it ignites some particles near the lighter and they follow the thread of the gas igniting it as it goes right?</p>
<p>If you don't have any inflammable gas, or not in a relevant quantity, you can light the lighter as many times as you want, that still, nothing will happen.</p>
<p>This is similar to what happens with thoughts in &quot;our mind&quot;. If you didn't have patterns of neurones more predisposed to be fired, when you sit still and after you master focusing on an &quot;anchor&quot; (breathing, mantra, or others), there should not be any thought arising right? But they do. And the most funny thing is they do arise besides not having any &quot;situation&quot; firing them. Right? There's no external lighter. So what is making them fire?</p>
<p>Think about this, when you're meditating, and you have gathered a certain amount of experience in doing it, you're able to see thoughts for what they are. Since you have practiced for a bit this you're, actually, able to look at them in very interesting ways. Since your mind is now used to the silence, you can perceive things such as the emotional charge thoughts have, you can see them &quot;rise&quot; from the unconscious to the &quot;surface&quot; of your mind. You can also see what they &quot;fire&quot; as they rise.</p>
<p>We use trauma mostly to talk about something that is &quot;bad&quot;. But a trauma is something that leaves a mark. If you were nurtured in good measure, that's a trauma too, it just has good repercussions. The thing is, everything is up until a certain age traumatic - in this sense that it leaves a mark.</p>
<p>If you then add the fact that many of the behaviours and thought patterns we have that make up our own &quot;minds&quot; are made when we don't have any tools to realise we are shaping our minds, or in other words, programming them, we could come to the conclusion that what you think is you is not actually you, or what you think are your original thoughts aren't actually your own thoughts, but the result of repeated inputs. If you then add to it the continuous flux of information to which we subject our minds in our current contemporary societies - even from a very young age, that incessantly &quot;print&quot; inside our minds these structures of thought - the more meditating becomes an important practice.</p>
<p>Have you ever thought why Advertising in prime time was (and still is) so expensive? And why advertisements pass repeated times at the same time frames? Because repetition will print in your brain interconnected sequences of neurones, like a product with a kind of emotion or feeling. Does that ad have a semi-clad girl? Or a happy family? Or the hint of adventure? Well these things are powerful triggers and, when repeated several times, they will print directly in your mind certain structures in certain patterns.</p>
<p>You might find yourself salivating unconsciously for a product that's totally unrelated to the emotion you're experiencing, just like Pavlov's dogs salivated for the sound of a bell (or a metronome).</p>
<p>By meditating you're actually giving yourself a tool to go through this. Literally, instead of having only external &quot;lighters&quot; to trigger your thought patterns you're giving yourself a &quot;lighter&quot; that will trigger whatever are the most &quot;rooted&quot; neurone meshes in your brain (you might think of it in terms of path of least resistance - since all neurones are fired by electrical impulses the ones that have a bigger hold in your brain or more ramifications will undoubtedly fire more easily).</p>
<p>A tool that also allows you to distance yourself from the &quot;thought&quot; objects that were &quot;printed&quot; in your brain. Because they're just &quot;thought&quot; objects.</p>
<p>Your mind can be seen as a store warehouse for &quot;thought-objects&quot; that replicate certain aspects of the external reality, apprehended through your life through your sense organs. This doesn't mean reality doesn't exist, it means that what you have inside your mind is not reality, although in many situations it will be as close to and useful almost as if it were literally bits of reality.</p>
<p>Say for instance you have a child, or something that you really love, when you think of it it probably triggers emotional responses and emotional patterns right? It's not that the object itself carries these emotions or patterns, it's because in your mind the object triggers these other things so, for you, this object is emotionally charged and both are the same. And you can confirm this. Take the object of your love to somebody who is totally unrelated to you and it and just watch them have the blandest of reactions, right? If the object carried these emotions, for instance your baby, then whenever another person entered in contact with him, he would experience the same feelings as you. But that doesn't quite happen right? If your baby starts crying you'll probably be worried and afflicted, but other people in the room will just go - wtf, just shut up that annoying brat.</p>
<p>Once you understand this - and the empiric experience of this is much stronger than the theoretical understanding of it - you're in a way a bit freer to choose things in life, I guess, and to understand yourself.</p>
<p>By exposing these thoughts and the subtle ramifications of the patterns that inhibit or trigger them you get more comfortable with them and, by repeating this process of sitting still and letting your mind unfold, you start to be able to, not control them but, be less controlled by them.</p>
<p>Because even though usually it's useful that the thought objects mimic reality to the point they create a reaction in you some times this may not be as good.</p>
<p>It's good that you're able to discern from an immediate threat, or pick up signals in a conversation that tell you something, it's good that a person you love triggers all the loveable patterns of emotion you have - otherwise you would be a robot - but at the same time, it's not good that some things trigger responses that you wish you wouldn't have - because this too is similar to a robot like experience.</p>
<p>In this sense by practicing you go through several stages, every time you re-focus your mind you're doing a mental pushup.</p>
<p>Some people will also be confronted with some thought structures and patterns they weren't aware of and that may increase some seemingly negative responses. Understanding and acceptance aren't always painless, but not facing that which brings you pain or sorrow will not help you.</p>
<p>Some times it's abstract, some times these patterns of thought are so deeply rooted that they can't be symbolised by language or idea, they just are.</p>
<p>You take a step towards freedom every time you overcome and understand these responses. And then you keep on repeating. Once you start clearing this, you start to settle more often in a specific electrifying state of restful awareness, where less and less you fire these patterns and you're just experiencing the &quot;lighter&quot; going on, maybe what some people call the divine spark? (just kidding…).</p>
<p>The things is, you should try it for yourself and you should stick with it. If you see a guy all pumped up from gym telling you you can do the same, obviously you're not expecting you'll achieve the same results by going to the gym for a month. You need to keep doing it right? I mean, you understand that right?</p>
<p>And so is the mind. It's repetition, either of inputs or behaviours, that shape what we are (along of course with nature), and by giving yourself time for them to unfold you're equipping yourself with a better knowledge of &quot;who&quot; you are. It also touches several aspects of creativity. Creativity is sort of the ability of coming up with new ways of organising or using things. If your mind is held in the sway of certain patterns of thinking it becomes very difficult for it to come up with new ways of organising information, whatever this information is, sound, painting materials, programming languages, tools, whatever.</p> ]]></description>
    </item>
  </channel>
</rss>
