Jekyll2023-08-10T14:28:41+00:00https://rsarai.xyz/feed.xmlRebeca SaraiA collection of everything that goes in my headRebeca SaraiThe architecture of open source applications [Audacity]2022-12-20T00:00:00+00:002022-12-20T00:00:00+00:00https://rsarai.xyz/architecture-open-source-audacity<p><br /></p>
<p><em>This post summarizes Chapter 2 of the book The architecture of open source applications - Vol I</em></p>
<p><img src="/images/2022-12-20-architecture-open-source-audacity/audacity.png" alt="Audacity's logo" title="Audacity's logo" /></p>
<p>Audacity is a sound recorder and audio editor initially written by Dominic Mazzoni in 1999 as a platform to develop and debug audio processing algorithms.</p>
<ul>
<li>Open source: <a href="https://github.com/audacity/audacity">https://github.com/audacity/audacity</a></li>
<li>Applies the principle of discoverable interface</li>
<li>Code principles are “try and be consistent”</li>
<li>Depends heavily on wxWidgets and PortAudio</li>
</ul>
<p>Description of audacity codebase:</p>
<blockquote>
<p>Audacity codebase is a mix of well-structured and less well-structured code… there are some impressive buildings, but you will also find run-down neighborhoods that are more like a shanty town.</p>
</blockquote>
<h2 id="points-that-caught-my-attention">Points that caught my attention:</h2>
<ul>
<li>
<p>Modular design was selected to drive the project towards better hiding of internal structure. By thinking carefully of an API, the interface gets more attention and forces the team to think of better abstractions, while also helping to avoid forks</p>
</li>
<li>
<p>Audacity has custom implementations for general functionalities because they were not provided initially by the libraries used</p>
</li>
<li>
<p>By using wxWidgets they ran into a lot of constraints during the life of the project</p>
</li>
<li>
<p>Evolutionary features are a good setup work for major changes</p>
</li>
<li>
<p>PortAudio and wxWdigets come with the price that there’s no flexibility to choose the abstractions. The result was less than pretty code for playback and recording because they need to handle threading in three different ways. The code also does more copying of data than it could do if they controlled the abstractions.</p>
</li>
<li>
<p>The wxWidgets API tempted the team into writing some verbose, hard-to-follow application code. The solution was to add a facade in front of wxWidgets to give better abstractions and cleaner application code.</p>
</li>
<li>
<p>Existing widgets were disconsidered on the TrackPanel due to lack of support and performance. This resulted in a messy module for a while.</p>
</li>
<li>
<p>A decision about what not to include in a program can be as important. It can lead to cleaner, safer code.</p>
</li>
<li>
<p>Audacity is a community effort.</p>
</li>
</ul>
<h2 id="audacity-polemic">Audacity polemic</h2>
<ul>
<li>
<p>Audacity used to prioritize keeping the community happy and discourage forks, this changed in 2021</p>
</li>
<li>
<p>An update on the terms of service caused a split in the community: “Data necessary for law enforcement, litigation and authorities’ requests (if any)” on the grounds of “Legitimate interest of WSM Group to defend its legal rights and interests”</p>
</li>
<li>
<p>By doing so, the team added networking features to the library to collect user’s personal information</p>
</li>
<li>
<p>This topic was scrutinized by the community and many decided to fork the libraries while audacity
clarified privacy police</p>
</li>
</ul>
<p>Check below a summary of my notes:</p>
<p><img src="/images/2022-12-20-architecture-open-source-audacity/all.png" alt="Mind map of audacity" title="Mind map of audacity" /></p>Rebeca SaraiThis post summarizes Chapter 2 of the book The architecture of open source applications - Vol IA second pass on the FTX collapse2022-11-26T00:00:00+00:002022-12-20T00:00:00+00:00https://rsarai.xyz/ftx-contagion<p>Below are some diagrams I made while following the chain of events that took place in November.
<br /></p>
<p><img src="/images/2022-11-26-ftx-contagion/1.png" /></p>
<p><br />
A summary of the players involved on this new crypto winter: Digital Currency Group (DCG), Genesis, Grayscale, SBF, 3AC, Alameda, Terra/Luna, Regulators.</p>
<p><img src="/images/2022-11-26-ftx-contagion/2.png" /></p>
<p><img src="/images/2022-11-26-ftx-contagion/3.png" /></p>
<p><br />
The original yield of the 2021 bull market and the incestuous relationship between Genesis and GBTC.</p>
<p><img src="/images/2022-11-26-ftx-contagion/4.png" /></p>
<p><img src="/images/2022-11-26-ftx-contagion/5.png" /></p>
<p><img src="/images/2022-11-26-ftx-contagion/6.png" /></p>
<p><br />
Hedge funds locked on iliquidy assets. While FTX, Genesis, Gemini appeared to do great and the impact of the failed GBTC ETF.</p>
<p><img src="/images/2022-11-26-ftx-contagion/7.png" /></p>
<p><br />
<a href="/ftx-fraud/">Details of the FTX collapse here</a></p>
<p><img src="/images/2022-11-26-ftx-contagion/8.png" /></p>
<p><img src="/images/2022-11-26-ftx-contagion/9.png" /></p>
<p><img src="/images/2022-11-26-ftx-contagion/10.png" /></p>
<p><img src="/images/2022-11-26-ftx-contagion/11.png" /></p>
<p><img src="/images/2022-11-26-ftx-contagion/12.png" /></p>
<p><img src="/images/2022-11-26-ftx-contagion/13.png" /></p>
<p><img src="/images/2022-11-26-ftx-contagion/14.png" /></p>
<h2 id="links">Links</h2>
<ul>
<li><a href="https://twitter.com/genesistrading/status/1590836594382032896">https://twitter.com/genesistrading/status/1590836594382032896</a></li>
<li><a href="https://twitter.com/DylanLeClair_/status/1592960066293927937">https://twitter.com/DylanLeClair_/status/1592960066293927937</a></li>
<li><a href="https://twitter.com/BlockFi/status/1590875997351866368">https://twitter.com/BlockFi/status/1590875997351866368</a></li>
<li><a href="https://twitter.com/autismcapital/status/1591569275642589184">https://twitter.com/autismcapital/status/1591569275642589184</a></li>
<li><a href="https://twitter.com/autismcapital/status/1591302842639593473">https://twitter.com/autismcapital/status/1591302842639593473</a></li>
<li><a href="https://twitter.com/TheBlock__/status/1592169646568144897">https://twitter.com/TheBlock__/status/1592169646568144897</a></li>
<li><a href="https://blockworks.co/news/gemini-circle-genesis-exposure">https://blockworks.co/news/gemini-circle-genesis-exposure</a></li>
<li><a href="https://www.reuters.com/legal/ftx-founder-bankman-fried-sued-us-court-over-yield-bearing-crypto-accounts-2022-11-16/">https://www.reuters.com/legal/ftx-founder-bankman-fried-sued-us-court-over-yield-bearing-crypto-accounts-2022-11-16/</a></li>
<li><a href="https://decrypt.co/114482/binance-be-guinea-pig-vitalik-buterins-proof-reserves-protocol-cz">https://decrypt.co/114482/binance-be-guinea-pig-vitalik-buterins-proof-reserves-protocol-cz</a></li>
<li><a href="https://www.theblock.co/post/117895/polychain-three-arrows-capital-lead-230-million-avalanche">https://www.theblock.co/post/117895/polychain-three-arrows-capital-lead-230-million-avalanche</a></li>
<li><a href="https://www.coindesk.com/business/2022/11/16/genesis-crypto-lending-unit-is-halting-customer-withdrawals-in-wake-of-ftx-collapse/">https://www.coindesk.com/business/2022/11/16/genesis-crypto-lending-unit-is-halting-customer-withdrawals-in-wake-of-ftx-collapse/</a></li>
<li><a href="https://www.theblock.co/post/187534/gemini-earn-unable-to-meet-customer-redemptions-as-genesis-unit-pauses-withdrawals">https://www.theblock.co/post/187534/gemini-earn-unable-to-meet-customer-redemptions-as-genesis-unit-pauses-withdrawals</a></li>
<li><a href="https://twitter.com/Grayscale/status/1592882142169944065">https://twitter.com/Grayscale/status/1592882142169944065</a></li>
<li><a href="https://twitter.com/AP_ArchPublic/status/1594386225200234496">https://twitter.com/AP_ArchPublic/status/1594386225200234496</a></li>
<li><a href="https://twitter.com/AP_ArchPublic/status/1594681951776014341">https://twitter.com/AP_ArchPublic/status/1594681951776014341</a></li>
<li><a href="https://twitter.com/ramahluwalia/status/1596236460092710912">https://twitter.com/ramahluwalia/status/1596236460092710912</a></li>
<li><a href="https://www.youtube.com/watch?v=IvAYINNcj50">https://www.youtube.com/watch?v=IvAYINNcj50</a></li>
<li><a href="https://www.coingecko.com/research/publications/exchange-withdrawal-ftx-collapse">https://www.coingecko.com/research/publications/exchange-withdrawal-ftx-collapse</a></li>
<li><a href="https://decrypt.co/114985/ftx-catastrophe-linked-terra-collapse">https://decrypt.co/114985/ftx-catastrophe-linked-terra-collapse</a></li>
<li><a href="https://www.nansen.ai/research/blockchain-analysis-the-collapse-of-alameda-and-ftx">https://www.nansen.ai/research/blockchain-analysis-the-collapse-of-alameda-and-ftx</a></li>
<li><a href="https://twitter.com/fintechfrank/status/1594820487582023680">https://twitter.com/fintechfrank/status/1594820487582023680</a></li>
<li><a href="https://twitter.com/TradFiWhale/status/1595235832297914369">https://twitter.com/TradFiWhale/status/1595235832297914369</a></li>
<li><a href="https://twitter.com/fintechfrank/status/1595205526127771648">https://twitter.com/fintechfrank/status/1595205526127771648</a></li>
<li><a href="https://www.mollywhite.net/etc/ftx-contagion">https://www.mollywhite.net/etc/ftx-contagion</a></li>
<li><a href="https://newsletter.protos.com/issues/sam-bankman-fried-lies-1475377">https://newsletter.protos.com/issues/sam-bankman-fried-lies-1475377</a></li>
<li><a href="https://newsletter.mollywhite.net/p/everything-sam-bankman-fried-is-doing">https://newsletter.mollywhite.net/p/everything-sam-bankman-fried-is-doing</a></li>
<li><a href="https://web3isgoinggreat.com/?id=sam-bankman-fried-arrested">https://web3isgoinggreat.com/?id=sam-bankman-fried-arrested</a></li>
</ul>Rebeca SaraiIn this post I collect my notes on the contagion of the FTX collapse.My notes on the FTX fraud2022-11-20T00:00:00+00:002022-12-20T00:00:00+00:00https://rsarai.xyz/ftx-fraud<p>Below are some diagrams I made while following the chain of events that took place in November.
<br /></p>
<p><img src="/images/2022-11-20-ftx-fraud/1.png" /></p>
<p><img src="/images/2022-11-20-ftx-fraud/2.png" /></p>
<p><img src="/images/2022-11-20-ftx-fraud/3.png" /></p>
<p><img src="/images/2022-11-20-ftx-fraud/4.png" /></p>
<p><img src="/images/2022-11-20-ftx-fraud/5.png" /></p>
<p><img src="/images/2022-11-20-ftx-fraud/6.png" /></p>
<p><img src="/images/2022-11-20-ftx-fraud/7.png" /></p>
<p><img src="/images/2022-11-20-ftx-fraud/8.png" /></p>
<p><img src="/images/2022-11-20-ftx-fraud/9.png" /></p>
<p><img src="/images/2022-11-20-ftx-fraud/10.png" /></p>
<p><img src="/images/2022-11-20-ftx-fraud/11.png" /></p>
<p><img src="/images/2022-11-20-ftx-fraud/12.png" /></p>
<p><img src="/images/2022-11-20-ftx-fraud/13.png" /></p>
<p><img src="/images/2022-11-20-ftx-fraud/14.png" /></p>
<p><img src="/images/2022-11-20-ftx-fraud/15.png" /></p>
<p><a href="/ftx-contagion/">Continues here</a></p>
<h2 id="links">Links</h2>
<ul>
<li><a href="https://www.coindesk.com/business/2022/11/02/divisions-in-sam-bankman-frieds-crypto-empire-blur-on-his-trading-titan-alamedas-balance-sheet/">https://www.coindesk.com/business/2022/11/02/divisions-in-sam-bankman-frieds-crypto-empire-blur-on-his-trading-titan-alamedas-balance-sheet/</a></li>
<li><a href="https://protos.com/is-sam-bankman-frieds-crypto-trading-firm-alameda-research-broke/">https://protos.com/is-sam-bankman-frieds-crypto-trading-firm-alameda-research-broke/</a></li>
<li><a href="https://twitter.com/cz_binance/status/1589283421704290306">https://twitter.com/cz_binance/status/1589283421704290306</a></li>
<li><a href="https://dirtybubblemedia.substack.com/p/is-alameda-research-insolvent">https://dirtybubblemedia.substack.com/p/is-alameda-research-insolvent</a></li>
<li><a href="https://twitter.com/carolinecapital/status/1589287457975304193">https://twitter.com/carolinecapital/status/1589287457975304193</a></li>
<li><a href="https://protos.com/how-the-battle-between-binance-and-ftx-went-from-bad-to-worse/">https://protos.com/how-the-battle-between-binance-and-ftx-went-from-bad-to-worse/</a></li>
<li><a href="https://protos.com/we-searched-for-ftxs-ether-and-we-have-questions/">https://protos.com/we-searched-for-ftxs-ether-and-we-have-questions/</a></li>
<li><a href="https://twitter.com/DylanLeClair_/status/1587890966580658177">https://twitter.com/DylanLeClair_/status/1587890966580658177</a></li>
<li><a href="https://twitter.com/cz_binance/status/1589374530413215744">https://twitter.com/cz_binance/status/1589374530413215744</a></li>
<li><a href="https://twitter.com/theData_Nerd/status/1589412341183000577">https://twitter.com/theData_Nerd/status/1589412341183000577</a></li>
<li><a href="https://twitter.com/TheBlock__/status/1589979338979434497">https://twitter.com/TheBlock__/status/1589979338979434497</a></li>
<li><a href="https://www.semafor.com/article/11/08/2022/before-deal-with-rival-ftx-scoured-wall-street-silicon-valley-billionaires-for-1-billion-lifeline">https://www.semafor.com/article/11/08/2022/before-deal-with-rival-ftx-scoured-wall-street-silicon-valley-billionaires-for-1-billion-lifeline</a></li>
<li><a href="https://twitter.com/LucasNuzzi/status/1590122590206824448">https://twitter.com/LucasNuzzi/status/1590122590206824448</a></li>
<li><a href="https://twitter.com/wassielawyer/status/1590025892994371584">https://twitter.com/wassielawyer/status/1590025892994371584</a></li>
<li><a href="https://twitter.com/binance/status/1590449161069268992">https://twitter.com/binance/status/1590449161069268992</a></li>
<li><a href="https://www.wsj.com/articles/ftx-tapped-into-customer-accounts-to-fund-risky-bets-setting-up-its-downfall-11668093732">https://www.wsj.com/articles/ftx-tapped-into-customer-accounts-to-fund-risky-bets-setting-up-its-downfall-11668093732</a></li>
<li><a href="https://www.coindesk.com/business/2022/11/10/ftx-digital-markets-assets-frozen-by-bahamian-regulator-bloomberg/">https://www.coindesk.com/business/2022/11/10/ftx-digital-markets-assets-frozen-by-bahamian-regulator-bloomberg/</a></li>
<li><a href="https://www.coindesk.com/business/2022/11/12/ftx-crypto-wallets-see-mysterious-late-night-outflows-totalling-more-than-380m/">https://www.coindesk.com/business/2022/11/12/ftx-crypto-wallets-see-mysterious-late-night-outflows-totalling-more-than-380m/</a></li>
<li><a href="https://twitter.com/zachxbt/status/1591276687228035074">https://twitter.com/zachxbt/status/1591276687228035074</a></li>
<li><a href="https://www.ft.com/content/f05fe9f8-ca0a-48d5-8ef2-7a4d813af558">https://www.ft.com/content/f05fe9f8-ca0a-48d5-8ef2-7a4d813af558</a></li>
<li><a href="https://twitter.com/SBF_FTX/status/1593014949487730688">https://twitter.com/SBF_FTX/status/1593014949487730688</a></li>
<li><a href="https://www.vox.com/future-perfect/23462333/sam-bankman-fried-ftx-cryptocurrency-effective-altruism-crypto-bahamas-philanthropy">https://www.vox.com/future-perfect/23462333/sam-bankman-fried-ftx-cryptocurrency-effective-altruism-crypto-bahamas-philanthropy</a></li>
<li><a href="https://twitter.com/GRDecter/status/1593272102047580161">https://twitter.com/GRDecter/status/1593272102047580161</a></li>
<li><a href="https://twitter.com/AutismCapital/status/1592563378408796165">https://twitter.com/AutismCapital/status/1592563378408796165</a></li>
<li><a href="https://www.ft.com/content/7e81ed85-8849-4070-a4e4-450195df08d7">https://www.ft.com/content/7e81ed85-8849-4070-a4e4-450195df08d7</a></li>
<li><a href="https://twitter.com/kadhim/status/1593222595390107649">https://twitter.com/kadhim/status/1593222595390107649</a></li>
<li><a href="https://twitter.com/Dogetoshi/status/1593233836867194880">https://twitter.com/Dogetoshi/status/1593233836867194880</a></li>
<li><a href="https://www.cnbctv18.com/cryptocurrency/ftx-new-ceo-john-ray-iii-a-quick-profile-15203471.htm">https://www.cnbctv18.com/cryptocurrency/ftx-new-ceo-john-ray-iii-a-quick-profile-15203471.htm</a></li>
<li><a href="https://twitter.com/PetrifyTCG/status/1591802968940199936">https://twitter.com/PetrifyTCG/status/1591802968940199936</a></li>
<li><a href="https://www.nansen.ai/research/blockchain-analysis-the-collapse-of-alameda-and-ftx">https://www.nansen.ai/research/blockchain-analysis-the-collapse-of-alameda-and-ftx</a></li>
</ul>Rebeca SaraiIn this post I collect my notes on the technical aspects of the FTX bankrupt🇧🇷 Resumo - O Grande Gatsby2022-10-10T00:00:00+00:002022-10-10T00:00:00+00:00https://rsarai.xyz/o-grande-gatsby<h2 id="sobre-o-enredo">Sobre o enredo</h2>
<p>A história gira em torno de um pequeno núcleo. Carraway é o narrador, um homem do oeste que se muda para o leste (para estudar, desenvolver uma nova carreira) e devido à casa onde mora conhece Gatsby. Gatsby é um homem rico e misterioso, que sempre promove festas em sua mansão (que fica ao lado da casa de Carraway). Ambos os homens estão conectados com um casal que também veio do oeste: Daisy e Tom, que por sua vez tem como amiga uma senhorita chamada Jordan.</p>
<p>Os primeiros capítulos servem para situar o leitor. Conhecemos o narrador Carraway que narra em 1º pessoa, com alguns comentários em diferentes pontos da linha do tempo. Gatsby é pintado como um homem rico, misterioso, que parece bastante disposto a conhecer o jovem Carraway. Daisy como a perfeita femme fatale. Jordan como mais uma moça da sociedade, um tanto moderna, um tanto independente. E Tom como o que imagino ser o homem comum daquela época, rico, infiel, racista e bonito.</p>
<p>O ponto principal da história é o relacionamento de Gatsby e Daisy. Ele tenta reconquistá-la, na verdade, reconquistá-la soa errado, vou ter que procurar uma palavra melhor. Ele sonha em apagar os anos que eles passaram separados graças ao dinheiro recém adquirido, de uma forma um tanto ingênua na minha opinião. Em um momento o grupo é confrontado com o relacionamento dos dois, Tom se usa desse momento para expor como Gatsby se tornou tão rico (contrabando? Alguma coisa ilegal certamente). A partir dai a trama se condensa e as tragédias vão se sucedendo até Gatsby estar morto, Tom e Daisy se mudando as pressas, Jordan noiva e Carraway lidando com detalhes do funeral</p>
<h2 id="sobre-a-obra">Sobre a obra</h2>
<p>No geral, achei a leitura bastante agradável, a história é curta, tem pouca enrolação, senti que quase tudo que está escrito é essencial para a trama. Gosto muito do narrador em primeira pessoa, que conta a história, mas que também pausa a narrativa para te dar uma opinião do futuro ou desenvolver um certo pensamento. Um detalhe sobre a escrita de Fitzgerald que me agradou muito foi a forma de descrever personagens, eu tive uma ideia muita clara de Tom e de Jordan. Daisy nem tanto, por achar a personagem um tanto genérica, não existe muito dela para entender. Com Gatsby é um pouco diferente, porque durante muito tempo só vemos o que ele quer deixar transparecer, conseguimos montar uma imagem melhor dele na discussão que ele tem com Tom e Daisy e nas histórias contadas por Carraway. Por fim, o que mais me incomodou nele foi: o homem ficou rico conduzindo negócios ilegais e mesmo assim ele me parece um ser ingenuo (pelo menos em relação a Daisy).</p>
<h2 id="nas-entrelinhas">Nas entrelinhas</h2>
<p>Sobre os temas abordados no livro, não li muitas análises até agora, mas sei que por ser um clássico esse livro toca em diversos temas que passaram por mim discretamente.</p>
<p>Gatsby fez de sua missão de vida enriquecer para poder reconquistar ou ainda tomar Daisy para si, tudo que ele fazia tinha o único propósito de agradá-la. É duro dizer que não foi suficiente, ele terminou sem amigos e sem Daisy, que fugiu com o marido assim que as coisas ficaram difíceis. No fundo, talvez ela o amasse, mas ela também tinha aquela mentalidade privilegiada de pensar que o mundo era obrigado a lhe proporcionar um certo padrão. Um marido rico e com dinheiro limpo, um modo de sempre escapar de situações de aperto</p>
<p>Tom e Daisy se entendiam muito bem, eles sabiam navegar as situações com cumplicidade e isso foi crucial no decorrer da história</p>
<p>Sinto que esse também é um livro sobre aparências, em como se é percebido e em como Gatsby queria ser percebido. Ele se moldava para ser cada vez mais como Daisy queria.</p>
<p>Em sua morte Gatsby estava só, o homem dava festas memoráveis para centenas de pessoas e nenhuma delas se dignou a lamentar sua morte. Ele se tornou um mito, uma história trágica que as pessoas contam a novos amigos, digo isso para dizer que as pessoas são ruins? Não realmente, acho que ele nunca foi acessível.</p>
<h2 id="esse-livro-em-uma-frase">Esse livro em uma frase</h2>
<p>Fantasias e máscaras podem ser úteis, no entanto é preciso ter cuidado para a fantasia não embaçar a realidade.</p>
<h2 id="citações">Citações</h2>
<ul>
<li>
<p>“I hope she’ll be a fool—that’s the best thing a girl can be in this world, a beautiful little fool.”</p>
</li>
<li>
<p>“‘Her voice is full of money,’ he said suddenly.”</p>
</li>
</ul>Rebeca SaraiAlguns comentários sobre o livro O Grande Gatsby de F. Scott FitzgeraldImplementing a liquidity pool with Python2022-09-03T00:00:00+00:002022-09-03T00:00:00+00:00https://rsarai.xyz/implementing-liquidity-pool<h2 id="table-of-contents">Table of Contents</h2>
<ol>
<li><a href="#org4ffb7b0">Introduction</a></li>
<li><a href="#org4b555b0">Constant Product Automated Market Maker</a></li>
<li><a href="#org3474843">Liquidity providers</a></li>
<li><a href="#org705dc63">Risks</a></li>
<li><a href="#org43ff1b3">Starting to code</a></li>
<li><a href="#orgceb7fc7">Creating a pool</a></li>
<li><a href="#org50b74bc">Adding liquidity to the pool</a></li>
<li><a href="#orga26b845">Swapping tokens</a></li>
<li><a href="#orge7f8f49">Conclusion</a></li>
<li><a href="#org701f625">Links</a></li>
</ol>
<p><br /></p>
<p>In this post, I will implement a liquidity pool using python and regular data structures, with no blockchain, and no contract code. The intention is to get a better understanding on how liquidity pools work economically, without diving in blockchain development details.</p>
<p><a id="org4ffb7b0"></a></p>
<h2 id="introduction">Introduction</h2>
<p>Liquidity pools are an essential part of Defi because they enable users to exchange tokens without the need of a trusted mediator, as is the case with centralized exchanges such as Coinbase.</p>
<p>This mechanism can be understood as a black box that enables unstoppable and automated trading based on prices defines by an algorithm.</p>
<ul>
<li>Unstoppable because once the mechanism is live, one should not be able to modify the implementation or even stop the mechanism. The only way to disable it is for users to stop using it.</li>
<li>Automated because the pricing of the assets is not dependent of users wanting to buy/sell, instead prices are defined algorithmically.</li>
</ul>
<p>Algorithms used to manage liquidity pools are called Automated Market Makers (AMM) and the simplest one is called: Constant Product Automated Market Maker.</p>
<p><a id="org4b555b0"></a></p>
<h2 id="constant-product-automated-market-maker">Constant Product Automated Market Maker</h2>
<p>Liquidity pools aid in avoiding large price swings by using algorithms to regulate the trade price.</p>
<p>The constant product formula is described below, and its result must remain constant despite the size of the trade, meaning that the total amount of liquidity on the pool remains constant:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">X * Y = K</code></li>
<li>X represents the number of tokens of type X</li>
<li>Y represents the number of tokens of type Y</li>
<li>K is the multiplication of the amount of both tokens and must remain constant</li>
</ul>
<p>This results in a seesaw effect, when the value of one token increases, the value of the other decreases, and vice versa. The formula dictates each transaction’s price, regardless of how much of either token is bought or sold at any given point.</p>
<p>Two details are extremely important to understand here:</p>
<ul>
<li>Smaller markets are subjected to high price variations on transactions since there’s not enough weight on the market, every transaction can impact the seesaw. So the more liquidity there is in a pool, the smaller impact trades will have on the value of the assets within that pool.</li>
<li>Since the value of assets is determined algorithmically, the system depends on the arbitrage of other actors to keep the current market price. Ex: buying items from the pool at a “discount” price and re-selling it at a secondary market for a profit.</li>
</ul>
<p><a id="org3474843"></a></p>
<h2 id="liquidity-providers">Liquidity providers</h2>
<p>As mentioned in the previous topic, smaller markets are subject to high price fluctuations due to the algorithmic nature of the pools. Liquidity providers are rewarded with transaction fees for allowing other traders to buy and sell using your liquidity. However, this is not a risk-free investment, one also needs to account for impermanent loss, which takes place when a trader places their tokens within a liquidity pool and then the price changes. The value of those tokens is now less than it was at the time of the investment, which means if you remove them now, their value will have decreased.</p>
<p>These losses are called impermanent because until you remove the investment from the liquidity pool, the loss is not materialized. You can wait to remove your liquidity until the exchange reaches a favorable point (but this can never come to fruition).</p>
<p><a id="org705dc63"></a></p>
<h2 id="risks">Risks</h2>
<p>Other than the risk for liquidity providers described in the previous section, there is also systemic risks of interacting with these mechanisms.</p>
<p>These markets are self-sustaining because they don’t need intermediaries. Formulas power smart contracts that provide security and confidence for investors. However, you need to verify in order to gain confidence in the project you are using, contracts can have bugs, founders can be ill-intentioned (e.g. create backdoors on their project to remove profits), and the ecosystem around the protocol can collapse (e.g.: Terra disaster), and etc.</p>
<p><a id="org43ff1b3"></a></p>
<h2 id="starting-to-code">Starting to code</h2>
<p>We want to enable the following functionalities:</p>
<ul>
<li>Trade one token for another freely</li>
<li>Add liquidity to the pool</li>
<li>Remove their share of liquidity of the pool</li>
</ul>
<p>Some general notes on how we want to approach this implementation:</p>
<ul>
<li>One liquidity pool should have two tokens</li>
<li>The pricing algorithm will be the Constant Product</li>
<li>All operations must keep the K value constant</li>
<li>The token ratio determines the pool’s pricing. For example, when someone buys DAI from the DAI/ETH pool, the volume of ETH increases, raising the price of DAI while lowering the price of ETH.</li>
<li>But the total price adjustment will depend on how much the person spent and how much the pool was altered.</li>
<li>For simplicity, we will not consider transaction fees.</li>
<li>Price is determined by: price_token_A = reserve_token_B / reserve_token_A (Y / X)</li>
</ul>
<p><a id="orgceb7fc7"></a></p>
<h2 id="creating-a-pool">Creating a pool</h2>
<p>Liquidity pools will be called Exchange and as mentioned previously the implementation will be made in Python.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Exchange</span><span class="p">:</span>
<span class="s">"""
Exchanges is how uniswap calls the liquidity pools
"""</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">token0_name</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">token1_name</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">name</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">symbol</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="bp">None</span><span class="p">:</span>
<span class="bp">self</span><span class="p">.</span><span class="n">token0</span> <span class="o">=</span> <span class="n">token0_name</span>
<span class="bp">self</span><span class="p">.</span><span class="n">token1</span> <span class="o">=</span> <span class="n">token1_name</span>
<span class="bp">self</span><span class="p">.</span><span class="n">reserve0</span> <span class="o">=</span> <span class="mi">0</span>
<span class="bp">self</span><span class="p">.</span><span class="n">reserve1</span> <span class="o">=</span> <span class="mi">0</span>
<span class="bp">self</span><span class="p">.</span><span class="n">fee</span> <span class="o">=</span> <span class="mi">0</span>
<span class="bp">self</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
<span class="bp">self</span><span class="p">.</span><span class="n">symbol</span> <span class="o">=</span> <span class="n">symbol</span>
<span class="bp">self</span><span class="p">.</span><span class="n">liquidity_providers</span> <span class="o">=</span> <span class="p">{}</span>
<span class="bp">self</span><span class="p">.</span><span class="n">total_supply</span> <span class="o">=</span> <span class="mi">0</span>
</code></pre></div></div>
<p>All the storage needed is reserve0 and reserve1, to hold the number of tokens of each asset. Other attributes are secondary and are used to ease implementation and keep a record of what’s happening in the pool.</p>
<p><a id="org50b74bc"></a></p>
<h2 id="adding-liquidity-to-the-pool">Adding liquidity to the pool</h2>
<p>Adding liquidity means updating the reserves to enable trading. When adding liquidity to a pool for the first time, the pool’s creator determines each asset’s initial price. However, if the pool’s pricing does not match that of the global crypto market, the liquidity provider risks losing money.</p>
<p>After the first time, the liquidity added to both pairs must match a minimal value, which is defined by <code class="language-plaintext highlighter-rouge">(amount0 * reserve1) / reserve0</code>.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Exchange</span>
<span class="c1"># ...
</span>
<span class="k">def</span> <span class="nf">quote</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">amount0</span><span class="p">,</span> <span class="n">reserve0</span><span class="p">,</span> <span class="n">reserve1</span><span class="p">):</span>
<span class="s">"""
Given some amount of an asset and pair reserves, returns an equivalent amount of
the other asset
"""</span>
<span class="k">assert</span> <span class="n">amount0</span> <span class="o">></span> <span class="mi">0</span><span class="p">,</span> <span class="s">'UniswapV2Library: INSUFFICIENT_AMOUNT'</span>
<span class="k">assert</span> <span class="n">reserve0</span> <span class="o">></span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">reserve1</span> <span class="o">></span> <span class="mi">0</span><span class="p">,</span> <span class="s">'UniswapV2Library: INSUFFICIENT_LIQUIDITY'</span>
<span class="k">return</span> <span class="p">(</span><span class="n">amount0</span> <span class="o">*</span> <span class="n">reserve1</span><span class="p">)</span> <span class="o">/</span> <span class="n">reserve0</span><span class="p">;</span>
<span class="k">def</span> <span class="nf">_add_liquidity</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">balance0</span><span class="p">,</span> <span class="n">balance1</span><span class="p">):</span>
<span class="s">"""
You always need to add liquidity to both types of coins
"""</span>
<span class="k">if</span> <span class="bp">self</span><span class="p">.</span><span class="n">reserve0</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="bp">self</span><span class="p">.</span><span class="n">reserve1</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="c1"># initializing pool
</span> <span class="n">amount0</span> <span class="o">=</span> <span class="n">balance0</span>
<span class="n">amount1</span> <span class="o">=</span> <span class="n">balance1</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">balance1Optimal</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">quote</span><span class="p">(</span><span class="n">balance0</span><span class="p">,</span> <span class="bp">self</span><span class="p">.</span><span class="n">reserve0</span><span class="p">,</span> <span class="bp">self</span><span class="p">.</span><span class="n">reserve1</span><span class="p">)</span>
<span class="k">if</span> <span class="n">balance1Optimal</span> <span class="o"><=</span> <span class="n">balance1</span><span class="p">:</span>
<span class="n">amount0</span> <span class="o">=</span> <span class="n">balance0</span>
<span class="n">amount1</span> <span class="o">=</span> <span class="n">balance1Optimal</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">balance0Optimal</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">quote</span><span class="p">(</span><span class="n">balance1</span><span class="p">,</span> <span class="bp">self</span><span class="p">.</span><span class="n">reserve1</span><span class="p">,</span> <span class="bp">self</span><span class="p">.</span><span class="n">reserve0</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">balance0Optimal</span> <span class="o"><=</span> <span class="n">balance0</span>
<span class="n">amount0</span> <span class="o">=</span> <span class="n">balance0Optimal</span>
<span class="n">amount1</span> <span class="o">=</span> <span class="n">balance1</span>
<span class="bp">self</span><span class="p">.</span><span class="n">reserve0</span> <span class="o">+=</span> <span class="n">amount0</span>
<span class="bp">self</span><span class="p">.</span><span class="n">reserve1</span> <span class="o">+=</span> <span class="n">amount1</span>
</code></pre></div></div>
<p>A visual example is the image below, the algorithm will force the user to always add the same amount of liquidity to both assets in the pool.</p>
<p><img src="/images/2022-09-03-implementing-liquidity-pool/add_liquidity_1.png" alt="Table with amount0, amount1, reserve0, reserve1" title="Table with amount0, amount1, reserve0, reserve1" /></p>
<p>This is extremely important when the pool is unbalanced, due to trades and negotiations that make the pool price equal to the market price.</p>
<p><img src="/images/2022-09-03-implementing-liquidity-pool/add_liquidity_2.png" alt="Table with amount0, amount1, reserve0, reserve1" title="Table with amount0, amount1, reserve0, reserve1" /></p>
<p><a id="orga26b845"></a></p>
<h2 id="swapping-tokens">Swapping tokens</h2>
<p>The implementation to swap tokens has more assertions than the actual code. The magic happens in the <code class="language-plaintext highlighter-rouge">get_amount_out</code> function, which calculates the correct amount out given the reserves of the pool.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Exchange</span>
<span class="c1"># ...
</span>
<span class="k">def</span> <span class="nf">get_amount_out</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">amount_in</span><span class="p">):</span>
<span class="s">"""
Given an input amount of an asset and pair reserves, returns the maximum output amount of the
other asset
(reserve0 + amount_in_with_fee) * (reserve1 - amount_out) = reserve1 * reserve0
"""</span>
<span class="k">assert</span> <span class="n">amount_in</span> <span class="o">></span> <span class="mi">0</span><span class="p">,</span> <span class="s">'UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT'</span>
<span class="k">assert</span> <span class="bp">self</span><span class="p">.</span><span class="n">reserve0</span> <span class="o">></span> <span class="mi">0</span> <span class="ow">and</span> <span class="bp">self</span><span class="p">.</span><span class="n">reserve1</span> <span class="o">></span> <span class="mi">0</span><span class="p">,</span> <span class="s">'UniswapV2Library: INSUFFICIENT_LIQUIDITY'</span>
<span class="n">amount_in_with_fee</span> <span class="o">=</span> <span class="n">amount_in</span> <span class="o">*</span> <span class="mi">1000</span> <span class="c1"># disconsidering the fee here: amount_in * 997
</span> <span class="n">numerator</span> <span class="o">=</span> <span class="n">amount_in_with_fee</span> <span class="o">*</span> <span class="bp">self</span><span class="p">.</span><span class="n">reserve1</span>
<span class="n">denominator</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">reserve0</span> <span class="o">*</span> <span class="mi">1000</span> <span class="o">+</span> <span class="n">amount_in_with_fee</span>
<span class="n">amount_out</span> <span class="o">=</span> <span class="n">numerator</span> <span class="o">/</span> <span class="n">denominator</span>
<span class="k">return</span> <span class="n">amount_out</span>
<span class="k">def</span> <span class="nf">swapExactTokensForTokens</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">amount0_in</span><span class="p">,</span> <span class="n">amount1_out_min</span><span class="p">):</span>
<span class="n">amount0_out</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">amount1_out</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">get_amount_out</span><span class="p">(</span><span class="n">amount0_in</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">amount1_out</span> <span class="o">>=</span> <span class="n">amount1_out_min</span><span class="p">,</span> <span class="s">'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT'</span>
<span class="k">assert</span> <span class="n">amount1_out</span> <span class="o">></span> <span class="mi">0</span><span class="p">,</span> <span class="s">'UniswapV2: INSUFFICIENT_OUTPUT_AMOUNT'</span>
<span class="k">assert</span> <span class="n">amount0_out</span> <span class="o"><</span> <span class="bp">self</span><span class="p">.</span><span class="n">reserve0</span> <span class="ow">and</span> <span class="n">amount1_out</span> <span class="o"><</span> <span class="bp">self</span><span class="p">.</span><span class="n">reserve1</span><span class="p">,</span> <span class="s">'UniswapV2: INSUFFICIENT_LIQUIDITY'</span>
<span class="n">balance0</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">reserve0</span> <span class="o">+</span> <span class="n">amount0_in</span> <span class="o">-</span> <span class="n">amount0_out</span>
<span class="n">balance1</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">reverve1</span> <span class="o">-</span> <span class="n">amount1_out</span>
<span class="n">balance0_adjusted</span> <span class="o">=</span> <span class="n">balance0</span> <span class="o">*</span> <span class="mi">1000</span>
<span class="n">balance1_adjusted</span> <span class="o">=</span> <span class="n">balance1</span> <span class="o">*</span> <span class="mi">1000</span>
<span class="k">assert</span> <span class="n">balance0_adjusted</span> <span class="o">*</span> <span class="n">balance1_adjusted</span> <span class="o">==</span> <span class="bp">self</span><span class="p">.</span><span class="n">reserve0</span> <span class="o">*</span> <span class="bp">self</span><span class="p">.</span><span class="n">reserve1</span> <span class="o">*</span> <span class="mi">1000</span><span class="o">**</span><span class="mi">2</span><span class="p">,</span> <span class="s">'UniswapV2: K'</span>
<span class="bp">self</span><span class="p">.</span><span class="n">reserve0</span> <span class="o">=</span> <span class="n">balance0</span>
<span class="bp">self</span><span class="p">.</span><span class="n">reserve1</span> <span class="o">=</span> <span class="n">balance1</span>
<span class="k">return</span> <span class="n">amount1_out</span>
</code></pre></div></div>
<p>Below is a set of example transactions, note that the difference between the amount in and the amount out increases as the transaction amount increases. This is what was described as the seesaw effect.</p>
<p><img src="/images/2022-09-03-implementing-liquidity-pool/trade.png" alt="Table showing the amount out depending on the amount in and reserves" title="Table showing the amount out depending on the amount in and reserves" /></p>
<p><a id="orge7f8f49"></a></p>
<h1 id="conclusion">Conclusion</h1>
<p>In this post, you just saw how to implement a liquidity pool using python and regular data structures, no blockchain, no contract code. A more complex implementation replicating the architecture used on smart contracts can be found <a href="https://github.com/rsarai/liquidity-pool">here</a>.</p>
<p><a id="org701f625"></a></p>
<h2 id="links">Links</h2>
<ul>
<li><a href="https://www.coindesk.com/learn/2021/08/20/what-is-an-automated-market-maker/">What Is an Automated Market Maker?</a></li>
<li><a href="https://www.blockchain-council.org/defi/crypto-liquidity-pools/">Know Everything about Crypto Liquidity Pools</a></li>
<li><a href="https://www.gemini.com/cryptopedia/what-is-a-liquidity-pool-crypto-market-liquidity">What Are Liquidity Pools?</a></li>
<li><a href="https://vitalik.ca/general/2017/06/22/marketmakers.html">On Path Independence</a></li>
<li><a href="https://medium.com/anchordao-lab/automated-market-maker-amm-algorithms-and-its-future-f2d5e6cc624a">A Mathematical View of Automated Market Maker (AMM) Algorithms and Its Future</a></li>
<li><a href="https://betterprogramming.pub/uniswap-smart-contract-breakdown-ea20edf1a0ff">https://betterprogramming.pub/uniswap-smart-contract-breakdown-ea20edf1a0ff</a></li>
<li><a href="https://ethereum.org/pt-br/developers/tutorials/uniswap-v2-annotated-code/">https://ethereum.org/pt-br/developers/tutorials/uniswap-v2-annotated-code/</a></li>
<li><a href="https://jeiwan.net/posts/programming-defi-uniswapv2-1/">https://jeiwan.net/posts/programming-defi-uniswapv2-1/</a></li>
<li><a href="https://github.com/Uniswap/v1-contracts/blob/c10c08d81d6114f694baa8bd32f555a40f6264da/contracts/uniswap_exchange.vy">https://github.com/Uniswap/v1-contracts/blob/c10c08d81d6114f694baa8bd32f555a40f6264da/contracts/uniswap_exchange.vy</a></li>
<li><a href="https://docs.uniswap.org/protocol/V1/guides/pool-liquidity">https://docs.uniswap.org/protocol/V1/guides/pool-liquidity</a></li>
<li><a href="https://docs.uniswap.org/protocol/V1/guides/connect-to-uniswap">https://docs.uniswap.org/protocol/V1/guides/connect-to-uniswap</a></li>
<li><a href="https://www.apifiny.com/academy-what-are-automated-market-makers-amm">https://www.apifiny.com/academy-what-are-automated-market-makers-amm</a></li>
</ul>Rebeca SaraiIn this post, I implement a liquidity pool using python and common data structures.The architecture of open source applications [Asterisk]2022-08-06T00:00:00+00:002022-12-20T00:00:00+00:00https://rsarai.xyz/architecture-open-source-asterisk<p><br /></p>
<p><em>This post summarizes Chapter 1 of the book The architecture of open source applications - Vol I</em></p>
<p>Asterisk is a project designed to manage communication systems, its general usage is for telephony, but phones can be replaced by any other type of communication channels. An initial look left the impression of a very traditional project, on a very traditional area (telephony), using a very traditional language (C language).</p>
<p>A summary of the modeling of the system can be resumed in: Asterisk core interacts with many modules to enable communication of different media types between channels. Modules called channel drivers provide channels that use dialplans to execute pre-defined behavior, channels also use bridging to interact with other channels in performatic ways.</p>
<p>Points that caught my attention:</p>
<ul>
<li>Channels are a central point of the system, and they are hardware specific. The design decision to deal with ambiguity was simple: create individual classes for each hardware and make them converge to a common abstraction, allowing features to work independently of the telephony in use. This is specified by ast_channel and ast_channel_tech</li>
<li>Unique language to configure dialplans. Language created is simple, expressive enough, and looks/is treated like a configuration</li>
<li>Application is heavily multithreaded, to make the debug process easier, all code that uses threads passes through debug wrappers.</li>
<li>Complex logic lies on codecs implementation (encode/decode media stream) and bridges implementation (optimized media transfer between channels)</li>
</ul>
<p>I found the <a href="https://github.com/asterisk/asterisk">project’s github</a> well organized and maintained, however, my lack of expertise with project pattern of C projects made it difficult to navigate through the code.</p>
<p>Check below a summary of my notes:</p>
<p><img src="/images/2022-08-06-architecture-open-source-asterisk/asterisk.png" alt="Mind map of asterisk" title="Mind map of asterisk" /></p>Rebeca SaraiThis post summarizes Chapter 1 of the book The architecture of open source applications - Vol IBrowsers degraded performance in background tabs2022-07-03T00:00:00+00:002022-07-03T00:00:00+00:00https://rsarai.xyz/browser-perf-inactive-tabs<p>In this post:</p>
<ol>
<li><a href="#org638f63e">TLDR</a></li>
<li><a href="#orgd834b73">Context</a></li>
<li><a href="#orgf9e1b7f">Technical details</a></li>
<li><a href="#orgfdfe677">Sources</a></li>
</ol>
<p><br /></p>
<p><a id="org638f63e"></a></p>
<h2 id="tldr">TLDR</h2>
<p>The load time for interactions in background tabs is 22x to 56x slower. This is undoubtedly tracked by Real user monitoring (RUM) solutions but is not discriminated against when defining alerts and budgets.</p>
<p><a id="orgd834b73"></a></p>
<h2 id="context">Context</h2>
<p>In a recent project, my challenge was to use available RUM (real user monitoring) metrics to define performance SLOs and error budgets. My initial thought was that the process would be simple since the historical data was available.</p>
<p>One special detail of the data was that it had a long tail. Imagine a distribution with an acceptable mean, a worrying p75, and a completely out-of-the-scope p90.</p>
<p><img src="/images/2022-07-03-browser-perf-inactive-tabs/distribution.png" alt="Two distributions. One ideal and one with a long tail" title="Two distributions. One ideal and one with a long tail" /></p>
<p>Outliers could not be excluded by analyzing percentiles, resulting in completely obscene performance metrics. This got me into an spiral of research and fear until I decided to analyze and sample the slow pages myself, to my surprise results were always close to the p50/p75.</p>
<p>One thing we noticed was that most of the slow events had “in foreground periods”, which was how our provider signaled moments where the user had put the page in the background and returned to it. This appeared to be a common thing among users, the realization paved the way to the discovery that some browsers (chrome in particular) slow down (or even suspend) execution of JavaScript on unfocused tabs.</p>
<p><a id="orgf9e1b7f"></a></p>
<h2 id="technical-details">Technical details</h2>
<p>Extracted from different posts:</p>
<ul>
<li>Background tabs set a per-frame simultaneous loading limit lower than for the foreground tabs. For example, Google Chrome limits the number of resources fetched to six when the tab is in the focus and to three when in the background per server/proxy. What it means is that only a limited number of requests from the browser are permitted to go to the network stack in parallel.</li>
<li>Background tabs are also restricted to CPU access. Google Chrome limits timers in the background to run only once per second. In addition, Chrome will delay timers to limit average CPU load to 1% of the processor core when running in background.</li>
<li>Load time difference when running in background
<ul>
<li>median load time for background interactions was 24x worse,</li>
<li>90th percentile was 22 times slower,</li>
<li>99th percentile loaded 56 times slower</li>
</ul>
</li>
</ul>
<p><a id="orgfdfe677"></a></p>
<h1 id="sources">Sources</h1>
<ul>
<li><a href="https://dzone.com/articles/did-you-know-that-background-tabs-in-your-browser">https://dzone.com/articles/did-you-know-that-background-tabs-in-your-browser</a></li>
<li><a href="https://chromestatus.com/feature/5527160148197376">https://chromestatus.com/feature/5527160148197376</a></li>
<li><a href="https://stackoverflow.com/questions/6032429/chrome-timeouts-interval-suspended-in-background-tabs">https://stackoverflow.com/questions/6032429/chrome-timeouts-interval-suspended-in-background-tabs</a></li>
<li><a href="https://plumbr.io/blog/performance-blog/background-tabs-in-browser-load-20-times-slower">https://plumbr.io/blog/performance-blog/background-tabs-in-browser-load-20-times-slower</a></li>
<li><a href="https://newrelic.com/blog/best-practices/expected-distributions-website-response-times">https://newrelic.com/blog/best-practices/expected-distributions-website-response-times</a></li>
</ul>Rebeca SaraiThis post describes how I discovered that the load time for interactions in background tabs is 22x to 56x slowerSolving Puzzles with Bitwise Operators2022-05-21T00:00:00+00:002022-05-21T00:00:00+00:00https://rsarai.xyz/bitwise-operators<p>In this post:</p>
<ol>
<li><a href="#org37b4ede">Rant on bitwise operations</a></li>
<li><a href="#orgf34dac3">The problem</a></li>
<li><a href="#orga41976e">Solution #1</a></li>
<li><a href="#org56cab37">Solution #2</a></li>
<li><a href="#org0f310e4">Links</a></li>
</ol>
<p><br /></p>
<p>I don’t really get bitwise operations. When to use them, and how. It’s weird. I know they are essential for hardware people, I know that sometimes is the only way you have to achieve linear complexity, and still, I struggle.</p>
<p>Studying a bit about it this weekend, I spot a question: “Why is it so difficult to understand how and when to use bitwise operators in programming?” I can relate to that. To the first answer to this post, I can not: “It’s only difficult if you don’t understand how computers actually work”. A peculiar and unhelpful claim, despite it, time to get back to the drawing board.</p>
<p><a id="org37b4ede"></a></p>
<h2 id="bitwise-operations">Bitwise operations</h2>
<ul>
<li>
<p><code class="language-plaintext highlighter-rouge">x << y</code>: Returns x with the bits shifted to the left by y places (and new bits on the right-hand side are zeros). This is the same as multiplying x by 2**y.</p>
</li>
<li>
<p><code class="language-plaintext highlighter-rouge">x >> y</code>: Returns x with the bits shifted to the right by y places. This is the same as //’ing x by 2**y.</p>
</li>
<li>
<p><code class="language-plaintext highlighter-rouge">x ^ y</code>: Does a “bitwise exclusive or”. Each bit of the output is the same as the corresponding bit in x if that bit in y is 0, and it’s the complement of the bit in x if that bit in y is 1.</p>
</li>
<li>
<p><code class="language-plaintext highlighter-rouge">x & y</code>: Does a “bitwise and”. Each bit of the output is 1 if the corresponding bit of x AND of y is 1, otherwise it’s 0.</p>
</li>
<li>
<p><code class="language-plaintext highlighter-rouge">x | y</code>: Does a “bitwise or”. Each bit of the output is 0 if the corresponding bit of x AND of y is 0, otherwise it’s 1.</p>
</li>
<li>
<p><code class="language-plaintext highlighter-rouge">~x</code>: Returns the complement of x - the number you get by switching each 1 for a 0 and each 0 for a 1. This is the same as -x - 1.</p>
<ul>
<li>Negative numbers always start with a 1. The smallest negative number is the largest binary value. 1111 is -1, 1110 is -2, 1101 is -3, etc
<ul>
<li>Examples
<ul>
<li>Find -4
<ul>
<li>4 = 100</li>
<li>Fill with zeros: 00100</li>
<li>Invert: 11011</li>
<li>Add 1: 11100</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="k">def</span> <span class="nf">is_odd</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">return</span> <span class="n">n</span> <span class="o">&</span> <span class="mi">1</span> <span class="o">!=</span> <span class="mi">0</span>
<span class="k">def</span> <span class="nf">is_opposite</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">m</span><span class="p">):</span>
<span class="k">return</span> <span class="p">(</span><span class="n">x</span> <span class="o">^</span> <span class="n">y</span><span class="p">)</span> <span class="o"><</span> <span class="mi">0</span>
<span class="k">def</span> <span class="nf">swap_vars</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="n">Int</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="n">Int</span> <span class="o">=</span> <span class="mi">3</span><span class="p">):</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">x</span> <span class="o">^</span> <span class="n">y</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">x</span> <span class="o">^</span> <span class="n">y</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">x</span> <span class="o">^</span> <span class="n">y</span>
<span class="k">def</span> <span class="nf">turn_off_kth</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">k</span><span class="p">):</span>
<span class="k">return</span> <span class="n">n</span> <span class="o">&</span> <span class="o">~</span><span class="p">(</span><span class="mi">1</span> <span class="o"><<</span> <span class="p">(</span><span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">turn_on_kth</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">k</span><span class="p">):</span>
<span class="k">return</span> <span class="n">n</span> <span class="o">|</span> <span class="p">(</span><span class="mi">1</span> <span class="o"><<</span> <span class="p">(</span><span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">check_if_kth_is_set</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">k</span><span class="p">):</span>
<span class="s">"""Returns 0 for not set, and the value for set"""</span>
<span class="k">return</span> <span class="n">n</span> <span class="o">&</span> <span class="p">(</span><span class="mi">1</span> <span class="o"><<</span> <span class="p">(</span><span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">toggle_the_kth_bit</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">k</span><span class="p">):</span>
<span class="s">"""Works because of XOR
n: 20 0b10100
k: 2 0b10
1 << (k - 1): 2 0b10
n ^ (1 << (k - 1)): 22 0b10110
"""</span>
<span class="k">return</span> <span class="n">n</span> <span class="o">^</span> <span class="p">(</span><span class="mi">1</span> <span class="o"><<</span> <span class="p">(</span><span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">unset_rightmost_set_bit</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="c1"># n: 49 0b110001
</span> <span class="c1"># n - 1: 48 0b110000
</span> <span class="c1"># n & (n - 1): 48 0b110000
</span> <span class="k">return</span> <span class="n">n</span> <span class="o">&</span> <span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">is_power_of_2</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="c1"># returns 0 if is power of 2
</span> <span class="k">return</span> <span class="n">n</span> <span class="o">&</span> <span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">find_index_of_rightmost_set_bit</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">&</span> <span class="mi">1</span><span class="p">):</span>
<span class="c1"># is odd number (ends with 1)
</span> <span class="k">return</span> <span class="mi">1</span>
<span class="n">x</span> <span class="o">=</span> <span class="p">(</span><span class="n">n</span> <span class="o">&</span> <span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">))</span> <span class="o">^</span> <span class="n">n</span>
<span class="n">pos</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">while</span> <span class="n">n</span><span class="p">:</span>
<span class="n">n</span> <span class="o">=</span> <span class="n">n</span> <span class="o">>></span> <span class="mi">1</span>
<span class="n">pos</span> <span class="o">=</span> <span class="n">pos</span> <span class="o">+</span> <span class="mi">1</span>
<span class="k">return</span> <span class="n">pos</span>
<span class="k">def</span> <span class="nf">find_position_of_only_set_bit</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">n</span> <span class="o">&</span> <span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">if</span> <span class="n">x</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">return</span> <span class="s">"Invalid"</span>
<span class="n">pos</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">while</span> <span class="n">n</span><span class="p">:</span>
<span class="n">n</span> <span class="o">=</span> <span class="n">n</span> <span class="o">>></span> <span class="mi">1</span>
<span class="n">pos</span> <span class="o">=</span> <span class="n">pos</span> <span class="o">+</span> <span class="mi">1</span>
<span class="k">return</span> <span class="n">pos</span>
<span class="k">def</span> <span class="nf">get_number_of_1</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="n">parity</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">while</span> <span class="n">n</span><span class="p">:</span>
<span class="n">n</span> <span class="o">=</span> <span class="n">n</span> <span class="o">&</span> <span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">parity</span> <span class="o">=</span> <span class="n">parity</span> <span class="o">+</span> <span class="mi">1</span>
<span class="k">return</span> <span class="n">parity</span>
</code></pre></div></div>
<p><a id="orgf34dac3"></a></p>
<h2 id="the-problem">The problem</h2>
<p>All this rant started with the following problem: Given an array of integers where every integer occurs three times except for one integer, which only occurs once, find and return the non-duplicated integer.</p>
<ul>
<li>Input - [6, 1, 3, 3, 3, 6, 6]
<ul>
<li>Output - 1</li>
</ul>
</li>
<li>Input - [13, 19, 13, 13]
<ul>
<li>Output - 19</li>
</ul>
</li>
</ul>
<p>Do this in O(N) time and O(1) space.</p>
<p>Obs: The problem was extracted from <a href="https://blog.quastor.org/p/daily-interview-problem-former-pinterest-coo-accuses-company-gender-bias">Daily Interview Problem / Former Pinterest COO accuses the company of Gender Bias!</a></p>
<p><a id="orga41976e"></a></p>
<h2 id="solution-1">Solution #1</h2>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="k">def</span> <span class="nf">find</span><span class="p">(</span><span class="n">l</span><span class="p">):</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">l</span><span class="p">:</span>
<span class="n">c</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">comparing_i</span> <span class="ow">in</span> <span class="n">l</span><span class="p">:</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="n">comparing_i</span><span class="p">:</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">c</span> <span class="o">+</span> <span class="mi">1</span>
<span class="k">if</span> <span class="n">c</span> <span class="o">></span> <span class="mi">1</span><span class="p">:</span>
<span class="n">c</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">break</span>
<span class="k">if</span> <span class="n">c</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="k">return</span> <span class="n">i</span>
<span class="k">return</span> <span class="o">-</span><span class="mi">1</span>
</code></pre></div></div>
<p>I have tests and all of them are passing. However, this is not the optimal solution.</p>
<p><a id="org56cab37"></a></p>
<h2 id="solution-2">Solution #2</h2>
<p>I still find the following solution a bit weird. I really don’t get bitwise operations.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="k">def</span> <span class="nf">find</span><span class="p">(</span><span class="n">nums</span><span class="p">):</span>
<span class="n">result_arr</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">32</span>
<span class="k">for</span> <span class="n">num</span> <span class="ow">in</span> <span class="n">nums</span><span class="p">:</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">32</span><span class="p">):</span>
<span class="n">bit</span> <span class="o">=</span> <span class="n">num</span> <span class="o">>></span> <span class="n">i</span> <span class="o">&</span> <span class="mi">1</span>
<span class="n">result_arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">result_arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">bit</span><span class="p">)</span> <span class="o">%</span> <span class="mi">3</span>
<span class="n">result</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">bit</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">result_arr</span><span class="p">):</span>
<span class="k">if</span> <span class="n">bit</span><span class="p">:</span>
<span class="n">result</span> <span class="o">+=</span> <span class="mi">2</span> <span class="o">**</span> <span class="n">i</span>
<span class="k">return</span> <span class="n">result</span>
</code></pre></div></div>
<hr />
<p>After some thought and study of the operations highlighted before, the logic becomes clear. Still, I don’t think this solution would come to me in an interview, I would stay with my old Python and write a solution fully tested in 10 minutes.</p>
<p><a id="org0f310e4"></a></p>
<h2 id="links">Links</h2>
<ul>
<li><a href="https://www.techiedelight.com/bit-hacks-part-1-basic/">https://www.techiedelight.com/bit-hacks-part-1-basic/</a></li>
<li><a href="https://medium.com/techie-delight/bit-manipulation-interview-questions-and-practice-problems-27c0e71412e7">Bit Manipulation: Interview Questions and Practice Problems</a></li>
<li><a href="https://graphics.stanford.edu/~seander/bithacks.html">https://graphics.stanford.edu/~seander/bithacks.html</a></li>
</ul>Rebeca SaraiIn this post I rant a bit about bitwise operators and review common ones.The Biggest Collapse in Crypto2022-05-18T00:00:00+00:002022-05-18T00:00:00+00:00https://rsarai.xyz/the-biggest-collapse-in-crypto<p><br /></p>
<p>The Terra ecosystem is a blockchain protocol that deploys decentralized stablecoins (crypto coin pegged to the dollar, e.g. 1UST = 1USD). Stablecoins are extremely crucial for the crypto community because it adds a layer of security to a highly stable asset. Decentralization is cool because it avoids the strings of the government.</p>
<p>The product of Terra is UST, a decentralized stablecoin with no collateral. The mechanism that makes the stablecoin work without any money baking it up (collateral) is an algorithm, UST can only be created by burning (destroying) LUNA and can only be burned (spent) by creating LUNA. So LUNA is a primary token (like ETH, or BTC) that is linked to the value of the stablecoin (UST). The collateral of the stable coin is the value of the underlying chain (Terra), which was thriving until recently due to a 20% interest rate for users buying LUNA and staking (which basically means putting on a protocol and promise not to sell). This high-interest rate brought a lot of attention of retail users (individual people, not funds).</p>
<p>This results in a complicated algorithm with a lot of financial implications and possible inflation, which is complex to explain in a post about fofoca. Know that all other attempts to make this work have failed, and there’s a general understanding that the hope to make decentralized stable coins is a fundamentally flawed assumption.</p>
<p>What’s the problem? The risk of de-pegging, which is the UST (stable coin) not being equal to the dollar, creating fear in people that the value will not return to the appropriated value, triggering a bank run of investors trying to collect gains, plugging the price of the coin even more. This is called the death spiral and was already deployed on regular financial markets. How big is this? In the last months, there were around 3B of UST invested.</p>
<p>At the beginning of May of 2022, someone attacked the protocol in the molds of the Soros black wednesday attack. With 100000 BTC, an undisclosed player was able to disrupt the market and create a bank run on Terra’s ecosystem. The fuse was the UST losing its pegg to the dollar, triggering the bank run.</p>
<p><img src="/images/2022-05-18-the-biggest-collapse-in-crypto/image-20220516-222613.png" />
<img src="/images/2022-05-18-the-biggest-collapse-in-crypto/image-20220516-221729.png" /></p>
<p>And LUNA, the sister coin, tied to UST:</p>
<p><img src="/images/2022-05-18-the-biggest-collapse-in-crypto/image-20220516-221609.png" />
<img src="/images/2022-05-18-the-biggest-collapse-in-crypto/image-20220516-222456.png" /></p>
<p>Word on the street is that the attacker was able to profit 800 million of dollars by shorting the market.</p>
<p>Crypto folks usually talk about the Lindy Effect, which is about the life expectancy of non-perishable things. The effect says that the longer a period something has survived to exist or be used in the present, it is also likely to have a longer remaining life expectancy. However, trusting blindly in this theory makes you susceptible to surprising events:</p>
<p><img src="/images/2022-05-18-the-biggest-collapse-in-crypto/image-20220516-220533.png" /></p>Rebeca SaraiIn this post I collect my notes on the meldown of Terra ecosystem.Learning Rust - creating a full-text search engine2022-05-15T00:00:00+00:002022-05-15T00:00:00+00:00https://rsarai.xyz/learning-rust-by-creating-fts-db<ol>
<li><a href="#orgfa86592">Read and load XML file</a></li>
<li><a href="#org6a4819a">Pass-By-Value or Pass-By-Reference</a></li>
<li><a href="#org7fddb5d">Read file</a></li>
<li><a href="#orge96434e">Processing the data</a></li>
<li><a href="#org2c6373b">Traits</a></li>
<li><a href="#org3ecb930">Searching for a string</a></li>
<li><a href="#orga513cf2">Pass by move</a></li>
</ol>
<p><br /></p>
<p>In this post, I try to reproduce the article “<a href="https://artem.krylysov.com/blog/2020/07/28/lets-build-a-full-text-search-engine/">Let’s build a Full-Text Search engine</a>” to learn more about full-text search databases and Rust. Please note: I graduated in computer engineering, the C language was the first language I ever saw in my life, and I use Python and JS daily. That’s the angle I will be using through the post.</p>
<p><a id="orgfa86592"></a></p>
<h2 id="read-and-load-xml-file">Read and load XML file</h2>
<p>Goal number one is to read some data from an XML export, after that load it in memory and perform searches on it. As a data source, I’m using the same part of the abstract of English Wikipedia described in the original article, with over 600K documents.</p>
<p>Google: “rust read xml file”. Check posts. Links led me to crates.io and to the quick-xml crate. More research also resulted in good answers (<a href="https://simplabs.com/blog/2020/12/31/xml-and-rust/">https://simplabs.com/blog/2020/12/31/xml-and-rust/</a>) which taught me different ways to parse files and different crates to use.</p>
<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">path</span><span class="p">::</span><span class="n">Path</span><span class="p">;</span>
<span class="k">fn</span> <span class="nf">load_documents</span><span class="p">(</span><span class="n">path_str</span><span class="p">:</span> <span class="nb">String</span><span class="p">)</span> <span class="p">{</span>
<span class="c">// Create a path to the desired file</span>
<span class="k">let</span> <span class="n">path</span> <span class="o">=</span> <span class="nn">Path</span><span class="p">::</span><span class="nf">new</span><span class="p">(</span><span class="n">path_str</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>The code above won’t work.</p>
<p><a id="org6a4819a"></a></p>
<h2 id="pass-by-value-or-pass-by-reference">Pass-By-Value or Pass-By-Reference</h2>
<p>Something that caught my attention is that you need to be intentional about passing parameters by reference or by value. The <code class="language-plaintext highlighter-rouge">Path</code> initializer expects a reference and not a struct <code class="language-plaintext highlighter-rouge">std::string::String</code>.</p>
<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">path</span><span class="p">::</span><span class="n">Path</span><span class="p">;</span>
<span class="k">fn</span> <span class="nf">load_documents</span><span class="p">(</span><span class="n">path_str</span><span class="p">:</span> <span class="o">&</span><span class="nb">str</span><span class="p">)</span> <span class="p">{</span>
<span class="c">// Create a path to the desired file</span>
<span class="k">let</span> <span class="n">path</span> <span class="o">=</span> <span class="nn">Path</span><span class="p">::</span><span class="nf">new</span><span class="p">(</span><span class="o">&</span><span class="n">path_str</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Rust is strictly a pass-by-value language. References are first-class citizens which means that references can be passed - by value - to functions. Therefore, you will often see intentional uses of references to avoid copying values to the stack of inner functions.</p>
<p>Another change in the code is <code class="language-plaintext highlighter-rouge">String</code> -> <code class="language-plaintext highlighter-rouge">&str</code> which is the appropriate format for when you pass a regular string as a parameter (check the snippet below).</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">String</code> is the dynamic heap string type, like Vec: use it when you need to own or modify your string data.</li>
<li><code class="language-plaintext highlighter-rouge">str</code> is an immutable sequence of UTF-8 bytes of dynamic length somewhere in memory. Since the size is unknown, one can only handle it behind a pointer (<code class="language-plaintext highlighter-rouge">&str</code>).</li>
</ul>
<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">path</span><span class="p">::</span><span class="n">Path</span><span class="p">;</span>
<span class="k">fn</span> <span class="nf">load_documents</span><span class="p">(</span><span class="n">path_str</span><span class="p">:</span> <span class="o">&</span><span class="nb">str</span><span class="p">)</span> <span class="p">{</span>
<span class="c">// Create a path to the desired file</span>
<span class="k">let</span> <span class="n">path</span> <span class="o">=</span> <span class="nn">Path</span><span class="p">::</span><span class="nf">new</span><span class="p">(</span><span class="o">&</span><span class="n">path_str</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">fn</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="k">let</span> <span class="n">documents</span> <span class="o">=</span> <span class="nf">load_documents</span><span class="p">(</span><span class="s">"data"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<ul>
<li>Reference #1: <a href="https://blog.ryanlevick.com/rust-pass-value-or-reference/">https://blog.ryanlevick.com/rust-pass-value-or-reference/</a></li>
<li>Reference #2: <a href="https://stackoverflow.com/questions/24158114/what-are-the-differences-between-rusts-string-and-str">https://stackoverflow.com/questions/24158114/what-are-the-differences-between-rusts-string-and-str</a></li>
<li>Reference #3: <a href="https://doc.rust-lang.org/rust-by-example/std_misc/file/open.html">https://doc.rust-lang.org/rust-by-example/std_misc/file/open.html</a></li>
</ul>
<p><a id="org7fddb5d"></a></p>
<h2 id="read-file">Read file</h2>
<p>Next step is to open a file in read-only mode to avoid accidents. To deal with failures, Rust bakes in a type called Result, whose Ok variants carry successful results—the count of bytes transferred, the file opened, and so on—and whose Err variants carry an error code indicating what went wrong. That is, <code class="language-plaintext highlighter-rouge">Result<T, E></code> could have one of two outcomes:</p>
<ul>
<li>Ok(T): An element T was found</li>
<li>Err(E): An error was found with element E</li>
</ul>
<p>Rust does not have exceptions, therefore all errors are handled using either the Result type or the panic macro.</p>
<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">path</span><span class="p">::</span><span class="n">Path</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">fs</span><span class="p">::</span><span class="n">File</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">io</span><span class="p">::</span><span class="nn">prelude</span><span class="p">::</span><span class="o">*</span><span class="p">;</span>
<span class="k">fn</span> <span class="nf">load_documents</span><span class="p">(</span><span class="n">path_str</span><span class="p">:</span> <span class="o">&</span><span class="nb">str</span><span class="p">)</span> <span class="p">{</span>
<span class="c">// Create a path to the desired file</span>
<span class="k">let</span> <span class="n">path</span> <span class="o">=</span> <span class="nn">Path</span><span class="p">::</span><span class="nf">new</span><span class="p">(</span><span class="o">&</span><span class="n">path_str</span><span class="p">);</span>
<span class="k">let</span> <span class="n">display</span> <span class="o">=</span> <span class="n">path</span><span class="nf">.display</span><span class="p">();</span>
<span class="c">// Open the path in read-only mode, returns `io::Result<File>`</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">file</span> <span class="o">=</span> <span class="k">match</span> <span class="nn">File</span><span class="p">::</span><span class="nf">open</span><span class="p">(</span><span class="o">&</span><span class="n">path</span><span class="p">)</span> <span class="p">{</span>
<span class="nf">Err</span><span class="p">(</span><span class="n">why</span><span class="p">)</span> <span class="k">=></span> <span class="nd">panic!</span><span class="p">(</span><span class="s">"couldn't open {}: {}"</span><span class="p">,</span> <span class="n">display</span><span class="p">,</span> <span class="n">why</span><span class="p">),</span>
<span class="nf">Ok</span><span class="p">(</span><span class="n">file</span><span class="p">)</span> <span class="k">=></span> <span class="n">file</span><span class="p">,</span>
<span class="p">};</span>
<span class="c">// Read the file contents into a string, returns `io::Result<usize>`</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">xml</span> <span class="o">=</span> <span class="nn">String</span><span class="p">::</span><span class="nf">new</span><span class="p">();</span>
<span class="k">match</span> <span class="n">file</span><span class="nf">.read_to_string</span><span class="p">(</span><span class="o">&</span><span class="k">mut</span> <span class="n">xml</span><span class="p">)</span> <span class="p">{</span>
<span class="nf">Err</span><span class="p">(</span><span class="n">why</span><span class="p">)</span> <span class="k">=></span> <span class="nd">panic!</span><span class="p">(</span><span class="s">"couldn't read {}: {}"</span><span class="p">,</span> <span class="n">display</span><span class="p">,</span> <span class="n">why</span><span class="p">),</span>
<span class="nf">Ok</span><span class="p">(</span><span class="mi">_</span><span class="p">)</span> <span class="k">=></span> <span class="nd">print!</span><span class="p">(</span><span class="s">"{} ok"</span><span class="p">,</span> <span class="n">display</span><span class="p">),</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">fn</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="k">let</span> <span class="n">documents</span> <span class="o">=</span> <span class="nf">load_documents</span><span class="p">(</span><span class="s">"data"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<ul>
<li>Reference #1: <a href="https://doc.rust-lang.org/rust-by-example/std_misc/file/open.html">https://doc.rust-lang.org/rust-by-example/std_misc/file/open.html</a></li>
<li>Reference #2: <a href="https://doc.rust-lang.org/rust-by-example/error/result.html">https://doc.rust-lang.org/rust-by-example/error/result.html</a></li>
<li>Reference #3: <a href="https://doc.rust-lang.org/std/result/">https://doc.rust-lang.org/std/result/</a></li>
</ul>
<p><a id="orge96434e"></a></p>
<h2 id="processing-the-data">Processing the data</h2>
<p>The step below will give you a string with all the content of the XML file. To actually use it and iterate over it, you will need to parse it to an object. quick-xml support an additional feature called serialize provided by another crate called serde which is a framework for serializing and deserializing Rust data structures.</p>
<p>Here a new word appeared: Traits. Let’s skip that and come back to it later.</p>
<p>The Serde ecosystem consists of data structures that know how to serialize and deserialize themselves. These data structures implement the Serde’s Serialize and Deserialize traits. Besides, Serde provides a derive macro to generate serialization implementations for structs in your own program.</p>
<p>This functionality is based on Rust’s #[derive] mechanism, just like what you would use to automatically derive implementations of the built-in Clone, Copy, Debug, or other traits. It is able to generate implementations for most structs and enums including ones with elaborate generic types or trait bounds.</p>
<p>The only step you need to do before running the following code is to add <code class="language-plaintext highlighter-rouge">serde = { version = "1.0", features = ["derive"] }</code> as a dependency in Cargo.toml.</p>
<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">fs</span><span class="p">::</span><span class="n">File</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">io</span><span class="p">::</span><span class="nn">prelude</span><span class="p">::</span><span class="o">*</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">path</span><span class="p">::</span><span class="n">Path</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">serde</span><span class="p">::</span><span class="n">Deserialize</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">quick_xml</span><span class="p">::</span><span class="nn">de</span><span class="p">::{</span><span class="n">from_str</span><span class="p">};</span>
<span class="nd">#[derive(Debug,</span> <span class="nd">Deserialize,</span> <span class="nd">PartialEq)]</span>
<span class="k">struct</span> <span class="n">Item</span> <span class="p">{</span>
<span class="n">title</span><span class="p">:</span> <span class="nb">String</span><span class="p">,</span>
<span class="n">url</span><span class="p">:</span> <span class="nb">String</span><span class="p">,</span>
<span class="n">r</span><span class="err">#</span><span class="n">abstract</span><span class="p">:</span> <span class="nb">String</span><span class="p">,</span>
<span class="n">id</span><span class="p">:</span> <span class="nb">Option</span><span class="o"><</span><span class="nb">u64</span><span class="o">></span>
<span class="p">}</span>
<span class="nd">#[derive(Debug,</span> <span class="nd">Deserialize,</span> <span class="nd">PartialEq)]</span>
<span class="k">struct</span> <span class="n">Document</span> <span class="p">{</span>
<span class="n">doc</span><span class="p">:</span> <span class="nb">Vec</span><span class="o"><</span><span class="n">Item</span><span class="o">></span>
<span class="p">}</span>
<span class="k">fn</span> <span class="nf">load_documents</span><span class="p">(</span><span class="n">path_str</span><span class="p">:</span> <span class="o">&</span><span class="nb">str</span><span class="p">)</span> <span class="k">-></span> <span class="n">Document</span> <span class="p">{</span>
<span class="c">// Create a path to the desired file</span>
<span class="k">let</span> <span class="n">path</span> <span class="o">=</span> <span class="nn">Path</span><span class="p">::</span><span class="nf">new</span><span class="p">(</span><span class="o">&</span><span class="n">path_str</span><span class="p">);</span>
<span class="k">let</span> <span class="n">display</span> <span class="o">=</span> <span class="n">path</span><span class="nf">.display</span><span class="p">();</span>
<span class="c">// Open the path in read-only mode, returns `io::Result<File>`</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">file</span> <span class="o">=</span> <span class="k">match</span> <span class="nn">File</span><span class="p">::</span><span class="nf">open</span><span class="p">(</span><span class="o">&</span><span class="n">path</span><span class="p">)</span> <span class="p">{</span>
<span class="nf">Err</span><span class="p">(</span><span class="n">why</span><span class="p">)</span> <span class="k">=></span> <span class="nd">panic!</span><span class="p">(</span><span class="s">"couldn't open {}: {}"</span><span class="p">,</span> <span class="n">display</span><span class="p">,</span> <span class="n">why</span><span class="p">),</span>
<span class="nf">Ok</span><span class="p">(</span><span class="n">file</span><span class="p">)</span> <span class="k">=></span> <span class="n">file</span><span class="p">,</span>
<span class="p">};</span>
<span class="c">// Read the file contents into a string, returns `io::Result<usize>`</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">xml</span> <span class="o">=</span> <span class="nn">String</span><span class="p">::</span><span class="nf">new</span><span class="p">();</span>
<span class="k">match</span> <span class="n">file</span><span class="nf">.read_to_string</span><span class="p">(</span><span class="o">&</span><span class="k">mut</span> <span class="n">xml</span><span class="p">)</span> <span class="p">{</span>
<span class="nf">Err</span><span class="p">(</span><span class="n">why</span><span class="p">)</span> <span class="k">=></span> <span class="nd">panic!</span><span class="p">(</span><span class="s">"couldn't read {}: {}"</span><span class="p">,</span> <span class="n">display</span><span class="p">,</span> <span class="n">why</span><span class="p">),</span>
<span class="nf">Ok</span><span class="p">(</span><span class="mi">_</span><span class="p">)</span> <span class="k">=></span> <span class="nd">print!</span><span class="p">(</span><span class="s">"{} ok"</span><span class="p">,</span> <span class="n">display</span><span class="p">),</span>
<span class="p">}</span>
<span class="nd">print!</span><span class="p">(</span><span class="s">"'{}'"</span><span class="p">,</span> <span class="n">xml</span><span class="p">);</span>
<span class="k">let</span> <span class="n">document</span><span class="p">:</span> <span class="n">Document</span> <span class="o">=</span> <span class="nf">from_str</span><span class="p">(</span><span class="o">&</span><span class="n">xml</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>
<span class="k">return</span> <span class="n">document</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<ul>
<li>Reference #1: <a href="https://serde.rs/data-model.html#types">https://serde.rs/data-model.html#types</a></li>
<li>Reference #2: <a href="https://serde.rs/derive.html">https://serde.rs/derive.html</a></li>
<li>Reference #3: <a href="https://crates.io/crates/quick-xml">https://crates.io/crates/quick-xml</a></li>
</ul>
<p><a id="org2c6373b"></a></p>
<h2 id="traits">Traits</h2>
<p>Traits are for Rust what interfaces are to other languages. However, not quite. A trait is a collection of methods defined for an unknown type: Self.</p>
<p>Traits appear to me as a way to support duck-typing, in which the implementation of the common methods stays in a separate class (called trait). This separate class has the syntax <code class="language-plaintext highlighter-rouge">impl <trait> for <type></code>. The crème de la crème here is that some traits can be automatically derived (compiler implements traits automatically).</p>
<p>They can be used as function parameters to allow the function to accept any type that can do x, where x is some behavior defined by a trait. We can also use trait bounds to refine and restrict generics, such as by saying we accept any type T that implements a specified trait.</p>
<ul>
<li>Reference #1: <a href="https://doc.rust-lang.org/rust-by-example/trait.html">https://doc.rust-lang.org/rust-by-example/trait.html</a></li>
<li>Reference #2: <a href="https://blog.logrocket.com/rust-traits-a-deep-dive/">https://blog.logrocket.com/rust-traits-a-deep-dive/</a></li>
</ul>
<p><a id="org3ecb930"></a></p>
<h2 id="searching-for-a-string">Searching for a string</h2>
<p>This part was quite intuitive. I first tried to search by term, using a simple contains, then a regex search.</p>
<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">fs</span><span class="p">::</span><span class="n">File</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">io</span><span class="p">::</span><span class="nn">prelude</span><span class="p">::</span><span class="o">*</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">path</span><span class="p">::</span><span class="n">Path</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">time</span><span class="p">::</span><span class="n">Instant</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">serde</span><span class="p">::</span><span class="n">Deserialize</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">regex</span><span class="p">::</span><span class="n">Regex</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">quick_xml</span><span class="p">::</span><span class="nn">de</span><span class="p">::{</span><span class="n">from_str</span><span class="p">};</span>
<span class="k">fn</span> <span class="nf">search_str</span><span class="p">(</span><span class="n">docs</span><span class="p">:</span> <span class="o">&</span><span class="nb">Vec</span><span class="o"><</span><span class="n">Item</span><span class="o">></span><span class="p">,</span> <span class="n">term</span><span class="p">:</span> <span class="o">&</span><span class="nb">str</span><span class="p">)</span> <span class="k">-></span> <span class="nb">Vec</span><span class="o"><</span><span class="nb">usize</span><span class="o">></span> <span class="p">{</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">indexes</span> <span class="o">=</span> <span class="nn">Vec</span><span class="p">::</span><span class="nf">with_capacity</span><span class="p">(</span><span class="mi">20</span><span class="p">);</span>
<span class="k">for</span> <span class="p">(</span><span class="n">pos</span><span class="p">,</span> <span class="n">e</span><span class="p">)</span> <span class="n">in</span> <span class="n">docs</span><span class="nf">.iter</span><span class="p">()</span><span class="nf">.enumerate</span><span class="p">()</span> <span class="p">{</span>
<span class="k">if</span> <span class="n">e</span><span class="py">.title</span><span class="nf">.contains</span><span class="p">(</span><span class="n">term</span><span class="p">)</span> <span class="p">{</span>
<span class="n">indexes</span><span class="nf">.push</span><span class="p">(</span><span class="n">pos</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">indexes</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">fn</span> <span class="nf">search_regex_str</span><span class="p">(</span><span class="n">docs</span><span class="p">:</span> <span class="o">&</span><span class="nb">Vec</span><span class="o"><</span><span class="n">Item</span><span class="o">></span><span class="p">,</span> <span class="n">term</span><span class="p">:</span> <span class="o">&</span><span class="nb">str</span><span class="p">)</span> <span class="k">-></span> <span class="nb">Vec</span><span class="o"><</span><span class="nb">usize</span><span class="o">></span> <span class="p">{</span>
<span class="k">let</span> <span class="n">formatted</span> <span class="o">=</span> <span class="nd">format!</span><span class="p">(</span><span class="s">r"(?i)\b{}\b"</span><span class="p">,</span> <span class="n">term</span><span class="p">);</span>
<span class="k">let</span> <span class="n">re</span> <span class="o">=</span> <span class="nn">Regex</span><span class="p">::</span><span class="nf">new</span><span class="p">(</span><span class="n">formatted</span><span class="nf">.as_str</span><span class="p">())</span><span class="nf">.unwrap</span><span class="p">();</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">indexes</span> <span class="o">=</span> <span class="nn">Vec</span><span class="p">::</span><span class="nf">with_capacity</span><span class="p">(</span><span class="mi">20</span><span class="p">);</span>
<span class="k">for</span> <span class="p">(</span><span class="n">pos</span><span class="p">,</span> <span class="n">e</span><span class="p">)</span> <span class="n">in</span> <span class="n">docs</span><span class="nf">.iter</span><span class="p">()</span><span class="nf">.enumerate</span><span class="p">()</span> <span class="p">{</span>
<span class="k">if</span> <span class="n">re</span><span class="nf">.is_match</span><span class="p">(</span><span class="o">&</span><span class="n">e</span><span class="py">.title</span><span class="p">)</span> <span class="p">{</span>
<span class="n">indexes</span><span class="nf">.push</span><span class="p">(</span><span class="n">pos</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">indexes</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">fn</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="k">let</span> <span class="n">documents</span> <span class="o">=</span> <span class="nf">load_documents</span><span class="p">(</span><span class="s">"data"</span><span class="p">);</span>
<span class="nd">println!</span><span class="p">(</span><span class="s">"</span><span class="se">\n\n</span><span class="s">Total {}"</span><span class="p">,</span> <span class="n">documents</span><span class="py">.doc</span><span class="nf">.len</span><span class="p">());</span>
<span class="k">let</span> <span class="n">now</span> <span class="o">=</span> <span class="nn">Instant</span><span class="p">::</span><span class="nf">now</span><span class="p">();</span>
<span class="k">let</span> <span class="n">result</span> <span class="o">=</span> <span class="nf">search_str</span><span class="p">(</span><span class="o">&</span><span class="n">documents</span><span class="py">.doc</span><span class="p">,</span> <span class="s">"cat"</span><span class="p">);</span>
<span class="k">let</span> <span class="n">elapsed</span> <span class="o">=</span> <span class="n">now</span><span class="nf">.elapsed</span><span class="p">();</span>
<span class="nd">println!</span><span class="p">(</span><span class="s">"Elapsed: {:.2?}"</span><span class="p">,</span> <span class="n">elapsed</span><span class="p">);</span>
<span class="nd">println!</span><span class="p">(</span><span class="s">"Search: cat; Len: {}; First: {}"</span><span class="p">,</span> <span class="n">result</span><span class="nf">.len</span><span class="p">(),</span> <span class="n">documents</span><span class="py">.doc</span><span class="p">[</span><span class="n">result</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span><span class="py">.title</span><span class="p">);</span>
<span class="k">let</span> <span class="n">now</span> <span class="o">=</span> <span class="nn">Instant</span><span class="p">::</span><span class="nf">now</span><span class="p">();</span>
<span class="k">let</span> <span class="n">result</span> <span class="o">=</span> <span class="nf">search_str</span><span class="p">(</span><span class="o">&</span><span class="n">documents</span><span class="py">.doc</span><span class="p">,</span> <span class="s">"Cat"</span><span class="p">);</span>
<span class="k">let</span> <span class="n">elapsed</span> <span class="o">=</span> <span class="n">now</span><span class="nf">.elapsed</span><span class="p">();</span>
<span class="nd">println!</span><span class="p">(</span><span class="s">"Elapsed: {:.2?}"</span><span class="p">,</span> <span class="n">elapsed</span><span class="p">);</span>
<span class="nd">println!</span><span class="p">(</span><span class="s">"Search: Cat; Len: {}; First: {}"</span><span class="p">,</span> <span class="n">result</span><span class="nf">.len</span><span class="p">(),</span> <span class="n">documents</span><span class="py">.doc</span><span class="p">[</span><span class="n">result</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span><span class="py">.title</span><span class="p">);</span>
<span class="k">let</span> <span class="n">now</span> <span class="o">=</span> <span class="nn">Instant</span><span class="p">::</span><span class="nf">now</span><span class="p">();</span>
<span class="k">let</span> <span class="n">result</span> <span class="o">=</span> <span class="nf">search_str</span><span class="p">(</span><span class="o">&</span><span class="n">documents</span><span class="py">.doc</span><span class="p">,</span> <span class="s">"CAT"</span><span class="p">);</span>
<span class="k">let</span> <span class="n">elapsed</span> <span class="o">=</span> <span class="n">now</span><span class="nf">.elapsed</span><span class="p">();</span>
<span class="nd">println!</span><span class="p">(</span><span class="s">"Elapsed: {:.2?}"</span><span class="p">,</span> <span class="n">elapsed</span><span class="p">);</span>
<span class="nd">println!</span><span class="p">(</span><span class="s">"Search: CAT; Len: {}; First: {}"</span><span class="p">,</span> <span class="n">result</span><span class="nf">.len</span><span class="p">(),</span> <span class="n">documents</span><span class="py">.doc</span><span class="p">[</span><span class="n">result</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span><span class="py">.title</span><span class="p">);</span>
<span class="p">}</span>
<span class="c">// Without regex using contains</span>
<span class="c">// Total 646392</span>
<span class="c">// Elapsed: 293.04ms</span>
<span class="c">// Search: cat; Len: 3176; First: Wikipedia: Telecommunications in Antigua and Barbuda</span>
<span class="c">// Elapsed: 287.67ms</span>
<span class="c">// Search: Cat; Len: 2014; First: Wikipedia: Catatonia</span>
<span class="c">// Elapsed: 227.92ms</span>
<span class="c">// Search: CAT; Len: 13; First: Wikipedia: CATIA</span>
<span class="c">// With regex</span>
<span class="c">// Total 646392</span>
<span class="c">// Elapsed: 4.20s</span>
<span class="c">// Search: cat; Len: 197; First: Wikipedia: Cat</span>
<span class="c">// Elapsed: 4.29s</span>
<span class="c">// Search: Cat; Len: 197; First: Wikipedia: Cat</span>
<span class="c">// Elapsed: 4.12s</span>
<span class="c">// Search: CAT; Len: 197; First: Wikipedia: Cat</span>
</code></pre></div></div>
<ul>
<li>Reference #1: <a href="https://doc.rust-lang.org/std/vec/struct.Vec.html#method.with_capacity">https://doc.rust-lang.org/std/vec/struct.Vec.html#method.with_capacity</a></li>
<li>Reference #2: <a href="https://doc.rust-lang.org/std/macro.format.html">https://doc.rust-lang.org/std/macro.format.html</a></li>
</ul>
<p><a id="orga513cf2"></a></p>
<h2 id="pass-by-move">Pass by move</h2>
<p>Back to the main function, at some point, I decided to pass the documents struct by value.</p>
<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="k">let</span> <span class="n">documents</span> <span class="o">=</span> <span class="nf">load_documents</span><span class="p">(</span><span class="s">"data"</span><span class="p">);</span>
<span class="nd">println!</span><span class="p">(</span><span class="s">"</span><span class="se">\n\n</span><span class="s">Total {}"</span><span class="p">,</span> <span class="n">documents</span><span class="py">.doc</span><span class="nf">.len</span><span class="p">());</span>
<span class="k">let</span> <span class="n">now</span> <span class="o">=</span> <span class="nn">Instant</span><span class="p">::</span><span class="nf">now</span><span class="p">();</span>
<span class="k">let</span> <span class="n">result</span> <span class="o">=</span> <span class="nf">search_str</span><span class="p">(</span><span class="n">documents</span><span class="py">.doc</span><span class="p">,</span> <span class="s">"cat"</span><span class="p">);</span> <span class="c">// <--------- HERE</span>
<span class="k">let</span> <span class="n">elapsed</span> <span class="o">=</span> <span class="n">now</span><span class="nf">.elapsed</span><span class="p">();</span>
<span class="nd">println!</span><span class="p">(</span><span class="s">"Elapsed: {:.2?}"</span><span class="p">,</span> <span class="n">elapsed</span><span class="p">);</span>
<span class="nd">println!</span><span class="p">(</span><span class="s">"Search: cat; Len: {}; First: {}"</span><span class="p">,</span> <span class="n">result</span><span class="nf">.len</span><span class="p">(),</span> <span class="n">documents</span><span class="py">.doc</span><span class="p">[</span><span class="n">result</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span><span class="py">.title</span><span class="p">);</span>
<span class="p">}</span>
<span class="c">// ERROR: raises the following on ``documents.doc[result[0]].title``:</span>
<span class="c">// borrow of moved value: `documents.doc`</span>
<span class="c">// value borrowed here after move</span>
<span class="c">// note: move occurs because `documents.doc` has type `std::vec::Vec<Item>`, which does not implement the `Copy` trait</span>
</code></pre></div></div>
<p>The Copy trait is only implementable by data types that can be put on the stack, and because Vec must go on the heap, it cannot implement Copy. What happens here is that the borrow checker is enforcing ownership to make memory safety guarantees without needing a garbage collector. Why ownership do you ask? To make sure different points of the flow won’t interfere with each other, imagine that, copying the <code class="language-plaintext highlighter-rouge">documents</code> would copy the Vec struct that contains three values: a length, a capacity, and a pointer to the actual data on the heap. The copy would lead to two pointers to the same data on the heap, if one of them is dropped, pointer in other Vec would now point to junk data.</p>
<p>This is all enforced at compile-time and guarantees that it won’t happen at running time.</p>
<ul>
<li>Reference #1: <a href="https://www.reddit.com/r/rust/comments/9fsyy3/rust_passbyvalue_or_passbyreference/">https://www.reddit.com/r/rust/comments/9fsyy3/rust_passbyvalue_or_passbyreference/</a></li>
<li>Reference #2: <a href="https://blog.logrocket.com/introducing-the-rust-borrow-checker/">https://blog.logrocket.com/introducing-the-rust-borrow-checker/</a></li>
<li>Reference #3: <a href="https://blog.logrocket.com/understanding-ownership-in-rust/">https://blog.logrocket.com/understanding-ownership-in-rust/</a></li>
</ul>
<hr />
<p>To be continued with a inverted index implementation.</p>Rebeca SaraiIn this post, I try to reproduce the article "Let's build a Full-Text Search engine" to learn more about full-text search databases and Rust.