<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: jahwi</title>
    <description>The latest articles on DEV Community by jahwi (@jahwi).</description>
    <link>https://dev.to/jahwi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F608512%2Fdbf7e624-8f47-435f-b7de-ccff35ea9a9f.png</url>
      <title>DEV Community: jahwi</title>
      <link>https://dev.to/jahwi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jahwi"/>
    <language>en</language>
    <item>
      <title>AI Newsie: Building a Serverless News Aggregator Bot with Rust, GPT-3, AWS Polly, and Sendgrid's API</title>
      <dc:creator>jahwi</dc:creator>
      <pubDate>Sun, 02 Apr 2023 19:36:02 +0000</pubDate>
      <link>https://dev.to/jahwi/ai-newsie-building-a-serverless-news-aggregator-bot-with-rust-gpt-3-aws-polly-and-sendgrids-api-2n09</link>
      <guid>https://dev.to/jahwi/ai-newsie-building-a-serverless-news-aggregator-bot-with-rust-gpt-3-aws-polly-and-sendgrids-api-2n09</guid>
      <description>&lt;p&gt;This weekend's project is a news aggregator bot that pulls articles from the New York Times, summarizes them with OpenAI's GPT-3, makes a text-to-speech recording with AWS Polly, and finally sends the email-recording combo via Sendgrid's API-- All written in Rust. I call it AI Newsie. The GitHub repo is &lt;a href="https://github.com/jahwi/ai_newsie"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here's how to set it up, and get it running on your very own AWS account (among other things) all for free!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BOQ3nKV5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/20hxlyfd8zt06t2td9m8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BOQ3nKV5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/20hxlyfd8zt06t2td9m8.png" alt="Newsletter Part Screenshot" width="800" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CxBA_X_Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vcu684u2sl61i4q0pfym.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CxBA_X_Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vcu684u2sl61i4q0pfym.png" alt="Recording Screenshot" width="426" height="206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring and Deploying AI Newsie
&lt;/h2&gt;

&lt;p&gt;To use the bot, one would need the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A Sendgrid API key - for sending emails&lt;/li&gt;
&lt;li&gt;A NYT API key - For grabbing news stories&lt;/li&gt;
&lt;li&gt;An OpenAI API Key - For processing and summarizing the news stories&lt;/li&gt;
&lt;li&gt;An AWS account: &lt;/li&gt;
&lt;li&gt;For access to AWS Polly (text-to-speech) and &lt;/li&gt;
&lt;li&gt;AWS Lambda (deploying the bot)&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  1. Setting up Sendgrid
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Sign up for Sendgrid and setup a &lt;a href="https://docs.sendgrid.com/ui/sending-email/sender-verification"&gt;sender identity&lt;/a&gt; and take note of your sendgrid sender email address. The most straightforward verfication route is Single Sender Verification.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1O2PYACn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z2ub0vyxp4dy20b8jww4.png" alt="Sender Verification" width="800" height="114"&gt;
&lt;/li&gt;
&lt;li&gt;After setting up a sender identity, create an API key by navigating to Settings -&amp;gt; API Keys -&amp;gt; Create API Key. Take note of this API key (not to be confused with the API Key ID) as it is hidden soon after generation.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  2. Setting up NYT API
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create a NYT developer account &lt;a href="https://developer.nytimes.com/"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Navigate to the My Apps page by clicking the dropdown at the upper left corner of the page and selecting "&lt;strong&gt;Apps&lt;/strong&gt;".&lt;/li&gt;
&lt;li&gt;Create an API key in the "&lt;strong&gt;API Keys&lt;/strong&gt;" section by clicking "&lt;strong&gt;Add Key&lt;/strong&gt;". Copy the API Key under the "&lt;strong&gt;Key&lt;/strong&gt;" header.&lt;/li&gt;
&lt;li&gt;Under the "&lt;strong&gt;APIs&lt;/strong&gt;" section, ensure "&lt;strong&gt;Article Search API&lt;/strong&gt;" is enabled.&lt;/li&gt;
&lt;li&gt;Below that, hit the "&lt;strong&gt;Save&lt;/strong&gt;" Button.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B2jKnBL6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/82t1fumyb25n725j1pxw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B2jKnBL6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/82t1fumyb25n725j1pxw.png" alt="NYT API setup" width="800" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Setting up OpenAI API
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create an account &lt;a href="https://platform.openai.com/"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Navigate to the API Keys page by clicking your account in the top left corner of the page and selecting "&lt;strong&gt;View API Keys&lt;/strong&gt;".&lt;/li&gt;
&lt;li&gt;Create a new API key by clicking the "&lt;strong&gt;Create new secret key&lt;/strong&gt;" button. Take note of the newly generated key.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vwrokXSe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ufdhz72m99y0i23aikc8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vwrokXSe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ufdhz72m99y0i23aikc8.png" alt="OpenAI API Setup" width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Setting up AWS
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;If you haven't already, setup an AWS account &lt;a href="https://aws.amazon.com/"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Navigate to the AWS Lambda service page by searching "&lt;strong&gt;Lambda&lt;/strong&gt;" in the search bar at the top of the page.&lt;/li&gt;
&lt;li&gt;Click "&lt;strong&gt;Create Function&lt;/strong&gt;" and select the "&lt;strong&gt;Author from scratch&lt;/strong&gt;" option.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MIRi-GsN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vsi7hhr7v5z6l53uoh4c.png" alt="Create an AWS Lambda Function" width="800" height="131"&gt;
&lt;/li&gt;
&lt;li&gt;Create a name for the new function, e.g. "NewsBot".&lt;/li&gt;
&lt;li&gt;For the "&lt;strong&gt;Runtime&lt;/strong&gt;" section, select "&lt;strong&gt;Provide your own bootstrap on Amazon Linux 2&lt;/strong&gt;", and under "&lt;strong&gt;Archictecture&lt;/strong&gt;", select "&lt;strong&gt;arm64&lt;/strong&gt;".&lt;/li&gt;
&lt;li&gt;Under the "&lt;strong&gt;Change Default Execution Role&lt;/strong&gt;" section, make sure "&lt;strong&gt;Create a new role with basic Lambda permissions&lt;/strong&gt;" is selected.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z2rrXxkG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hn9ruvoimyn7aagnjmju.png" alt="AWS Lambda Function creation" width="800" height="675"&gt;
&lt;/li&gt;
&lt;li&gt;Click "&lt;strong&gt;Create Function&lt;/strong&gt;".&lt;/li&gt;
&lt;li&gt;Add AWS Polly permissions for the bot by navigating to the "&lt;strong&gt;Configuration&lt;/strong&gt;" section -&amp;gt; clicking "&lt;strong&gt;Permissions&lt;/strong&gt;", then clicking the link under Role Name in the "&lt;strong&gt;Execution Role&lt;/strong&gt;" header.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BCeHLCjI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wkyelyw6jbwfocupbmzp.png" alt="Click Link to Edit Role" width="800" height="271"&gt;
&lt;/li&gt;
&lt;li&gt;In the "&lt;strong&gt;Permissions&lt;/strong&gt;" tab, click the "&lt;strong&gt;Add Permissions&lt;/strong&gt;" button, then select "&lt;strong&gt;Attach Policy&lt;/strong&gt;".
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vf7KECZa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r69k5rxux7ricsp7t0sa.png" alt="Attach Policy" width="800" height="171"&gt;
&lt;/li&gt;
&lt;li&gt;Search for and select "&lt;strong&gt;AmazonPollyReadOnlyAccess&lt;/strong&gt;" in the permissions search bar, then click "&lt;strong&gt;Add Permissions&lt;/strong&gt;".
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C2-5f5Nh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fpe4p8jd7qg37em5wt9x.png" alt="Amazon Polly Permissions" width="800" height="256"&gt;
&lt;/li&gt;
&lt;li&gt;Back to the Lambda Functions page, under the "&lt;strong&gt;Configuration&lt;/strong&gt;" tab, select "&lt;strong&gt;Environment Variables&lt;/strong&gt;".&lt;/li&gt;
&lt;li&gt;Configure the environment variables as follows, by clicking the "&lt;strong&gt;Edit&lt;/strong&gt;" button:
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BFi6i4XD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/76mglw2nmy1pjmwg217b.png" alt="AWS Lambda Function Environment Variables" width="800" height="340"&gt;
&lt;/li&gt;
&lt;li&gt;Click the "&lt;strong&gt;Save&lt;/strong&gt;" button after setting environment variables.&lt;/li&gt;
&lt;li&gt;Under the "&lt;strong&gt;General Configuration&lt;/strong&gt;" menu, click "&lt;strong&gt;Edit&lt;/strong&gt;" and change the timeout to "&lt;strong&gt;2min 0sec&lt;/strong&gt;", and save.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--idLjTVBX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/exl9v4ne0buppvg74lbr.png" alt="Gen Config" width="800" height="69"&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ha-fTBCy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o5l7b9xvpprf2c47o934.png" alt="Timeout Setting" width="455" height="117"&gt;
&lt;/li&gt;
&lt;li&gt;Grab a pre-built bootstrap from &lt;a href="https://github.com/jahwi/ai_newsie/releases"&gt;here&lt;/a&gt;, and download bootstrap.zip from the latest version. Alternatively, you can build your own bootstrap from the repository, but that is beyond the scope of this post.&lt;/li&gt;
&lt;li&gt;Back to your AWS Lambda function, in the "&lt;strong&gt;Code&lt;/strong&gt;" section, scroll down and click "&lt;strong&gt;Upload From&lt;/strong&gt;" -&amp;gt; "&lt;strong&gt;.zip file&lt;/strong&gt;".
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FJ1LkHTl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r25eigkllbpwpjio1eyn.png" alt="Upload Bootstrap" width="800" height="96"&gt;
&lt;/li&gt;
&lt;li&gt;Once the zip has been uploaded, test your function works by navigating to the "Test" tab and clicking the "&lt;strong&gt;Test&lt;/strong&gt;" button. The function should send your AI-generated email to your desired destination, via your sendgrid sender email.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gzeXmYjy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/84pulgeayvr7aosfnrkd.png" alt="Test Screen" width="800" height="109"&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qzaGiDxj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y880zr6sgo18fham8s2b.png" alt="Log 1" width="635" height="164"&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e_K37HAQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ba5lr2xwgsvhpema6b1u.png" alt="Log 2" width="800" height="165"&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yHlZdIqj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5845voonb9v5t20oxqzt.png" alt="Email Result" width="800" height="71"&gt;
&lt;/li&gt;
&lt;li&gt;Check the Log Output to confirm the bot ran as expected.&lt;/li&gt;
&lt;li&gt;Finally, you can schedule the bot to run daily by navigating to the "&lt;strong&gt;Triggers&lt;/strong&gt;" section of the "&lt;strong&gt;Configuration&lt;/strong&gt;" tab and clicking "&lt;strong&gt;Add Trigger&lt;/strong&gt;".&lt;/li&gt;
&lt;li&gt;Then, select &lt;strong&gt;EventBridge&lt;/strong&gt;, -&amp;gt; "&lt;strong&gt;Create a new rule&lt;/strong&gt;" and configuring "&lt;strong&gt;Rule Name&lt;/strong&gt;" as "Daily_Newsletter", "&lt;strong&gt;Rule Description&lt;/strong&gt;" as "&lt;strong&gt;Run the newsbot daily&lt;/strong&gt;", and "&lt;strong&gt;Schedule Expression&lt;/strong&gt;" as "&lt;strong&gt;rate(1 day)&lt;/strong&gt;", then click "&lt;strong&gt;Add&lt;/strong&gt;".
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sGiTi0z5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dd7lvfx7ma1feqnxs7dl.png" alt="Seting a trigger" width="800" height="626"&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The services used in this project are offered under freemium/capped payment models, and so as long as your usage of these services (as the AI Newsie does) is under the stated limits, it will cost nothing to run the bot monthly. OpenAI gives $18 in free credits on creating a new account for three months, for example.&lt;/p&gt;

&lt;p&gt;Thanks for reading. Comments and PRs welcome!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rust</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Skipping to the Good Parts: Implementing Netflix's Skip Intro Feature with Python Video Processing</title>
      <dc:creator>jahwi</dc:creator>
      <pubDate>Sun, 05 Feb 2023 13:42:11 +0000</pubDate>
      <link>https://dev.to/jahwi/skipping-to-the-good-parts-implementing-netflixs-skip-intro-feature-with-python-video-processing-3gh5</link>
      <guid>https://dev.to/jahwi/skipping-to-the-good-parts-implementing-netflixs-skip-intro-feature-with-python-video-processing-3gh5</guid>
      <description>&lt;p&gt;Netflix’s Skip Intro feature is about as iconic as the service itself, allowing subscribers to skip past intro and outro portions of tv shows. Since then, other streaming services have adopted this feature, making it a staple of the streaming world. &lt;/p&gt;

&lt;p&gt;Recently, I began thinking about implementing this feature and this led me to make a &lt;a href="https://github.com/jahwi/similar-vid" rel="noopener noreferrer"&gt;small library&lt;/a&gt; to find similar portions in videos. It does this by hashing videos into frames, hashing these frames, and comparing similar frames between each comparison video and a reference video.&lt;/p&gt;

&lt;p&gt;I decided to test this library on my favourite recently-cancelled Netflix show, Inside Job:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="c1"&gt;# Import the library
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;similar_vid.similar_secs&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Similar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;save&lt;/span&gt;

&lt;span class="c1"&gt;# Load the file paths
&lt;/span&gt;&lt;span class="n"&gt;file1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;videos//inside_job//01.mkv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;file2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;videos//inside_job//02.mkv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;file3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;videos//inside_job//03.mkv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;file4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;videos//inside_job//04.mkv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;file5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;videos//inside_job//05.mkv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Hash the videos
&lt;/span&gt;    &lt;span class="n"&gt;inside_job&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Similar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;file1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;comp_arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;file2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file5&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="c1"&gt;# Match the videos
&lt;/span&gt;    &lt;span class="n"&gt;inside_job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;threshold&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;inside_job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# use the library's save function to save class fields as JSON for further use
&lt;/span&gt;    &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inside_job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;outs//matches.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above, we import the Similar class from my &lt;a href="https://github.com/jahwi/similar-vid" rel="noopener noreferrer"&gt;similar-vid&lt;/a&gt; library and pass it the reference video and an array of comparison videos. We then use the &lt;code&gt;match&lt;/code&gt; method to speficy that we only want matches that are at least 15 seconds long. The library then hashes and matches the videos as such:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9p9ugywiegvgykp8mq59.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9p9ugywiegvgykp8mq59.png" alt="Screenshot of console output showing the library matching frames between videos" width="560" height="283"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Description: A screenshot of the console showing the hashing and matching process.&lt;/p&gt;

&lt;p&gt;These hashes are then stored in the &lt;code&gt;matches&lt;/code&gt; field of the class instance as a list of dictionaries. Below that, we print the matches and use the library’s &lt;code&gt;save&lt;/code&gt; method to save the matches to a json file:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7yljn09jm902z6kdzxoj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7yljn09jm902z6kdzxoj.png" alt="A screenshot of the console showing the matching frames." width="620" height="80"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The returned arrays of the “matches” key, if any, are the beginning and ending matching seconds of the comparison video, respectively.&lt;/p&gt;

&lt;p&gt;We can then pass this as context to the frontend. Using Javascript to modify the video’s &lt;code&gt;currentTime&lt;/code&gt; property, we can skip the intro portion:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcn4pkc067y44cdhj4nvm.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcn4pkc067y44cdhj4nvm.gif" alt="Screenshot video showing implementing the Skip Intro feature implemented in the frontend" width="600" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As can be seen in the above gif, the Skip Intro button appears over the intro portion.&lt;/p&gt;

&lt;p&gt;The similar_vid library can be found here: &lt;a href="https://github.com/jahwi/similar-vid" rel="noopener noreferrer"&gt;https://github.com/jahwi/similar-vid&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading.&lt;/p&gt;

</description>
      <category>announcement</category>
      <category>devto</category>
      <category>web3</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>A Simple user input collection, validation, and conversion library in Rust</title>
      <dc:creator>jahwi</dc:creator>
      <pubDate>Thu, 13 May 2021 15:56:44 +0000</pubDate>
      <link>https://dev.to/jahwi/a-simple-user-input-collection-validation-and-conversion-library-in-rust-34cj</link>
      <guid>https://dev.to/jahwi/a-simple-user-input-collection-validation-and-conversion-library-in-rust-34cj</guid>
      <description>&lt;p&gt;Writing a CLI program often requires reading and parsing user input. Today, we will create a &lt;a href="https://www.rust-lang.org/" rel="noopener noreferrer"&gt;Rust&lt;/a&gt; library that allows us to read and convert String input from STDIN into a number of primitive types such as i32, u32, usize, etc.&lt;/p&gt;

&lt;p&gt;This article is suitable for new and prospective Rust programmers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up
&lt;/h2&gt;

&lt;p&gt;We begin, as most projects do, with &lt;a href="https://doc.rust-lang.org/cargo/" rel="noopener noreferrer"&gt;Cargo&lt;/a&gt; - Rust's package manager. &lt;/p&gt;

&lt;p&gt;In the command line, Initialize a new project directory named &lt;code&gt;get_input&lt;/code&gt; as shown below:&lt;/p&gt;

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

cargo new &lt;span class="nt"&gt;--lib&lt;/span&gt; get_input


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

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;--lib&lt;/code&gt; flag tells Cargo that we're creating a new library, instead of a binary. If all went well, you should see output similar to the below:&lt;/p&gt;

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

C:&lt;span class="se"&gt;\U&lt;/span&gt;sers&lt;span class="se"&gt;\r&lt;/span&gt;usty&amp;gt;cargo new &lt;span class="nt"&gt;--lib&lt;/span&gt; get_input
     Created library &lt;span class="sb"&gt;`&lt;/span&gt;get_input&lt;span class="sb"&gt;`&lt;/span&gt; package


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

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note: If there's an existing folder of the same name in the current directory, change the project name to something else, like &lt;code&gt;get_input_tutorial&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Library Design
&lt;/h2&gt;

&lt;p&gt;Before we write our first line of code, we need to determine, on a high level, how our code will function. What are the requirements and goals of this small library? &lt;/p&gt;

&lt;p&gt;Overall, we want our code to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Collect user input from STDIN,&lt;/li&gt;
&lt;li&gt;Validate that input,&lt;/li&gt;
&lt;li&gt;Optionally, convert that input to another type, and finally&lt;/li&gt;
&lt;li&gt;Perform some logic with the collected input.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Crate Root
&lt;/h2&gt;

&lt;p&gt;When creating libraries, Cargo creates a special file called the &lt;strong&gt;crate root&lt;/strong&gt; in the project's &lt;strong&gt;&lt;code&gt;src&lt;/code&gt;&lt;/strong&gt; directory. Packages in Rust are called crates, and one of the most important files in a library crate is the root, named &lt;code&gt;lib.rs&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We'll be working with the crate root today, located at &lt;code&gt;[project_path]\get_input\src\lib.rs&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;a href="http://lib.rs" rel="noopener noreferrer"&gt;lib.rs&lt;/a&gt; file, Cargo automatically generates a sample test module. This is one of Rust's several nudges towards writing robust, well-tested software. Ultimately, we should all aim to write well-tested code. &lt;/p&gt;

&lt;p&gt;So anyway, go ahead and &lt;strong&gt;CTRL+A,  DEL&lt;/strong&gt; the tests till you are left with a blank page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bringing Libraries Into Scope
&lt;/h2&gt;

&lt;p&gt;With the &lt;code&gt;use&lt;/code&gt; keyword, we'll bring the required libraries into scope. For now, we only need a module from Rust's standard library: the &lt;strong&gt;&lt;a href="https://doc.rust-lang.org/std/io/index.html" rel="noopener noreferrer"&gt;io&lt;/a&gt;&lt;/strong&gt; module. This library is one that provides Input/Output functionality, which we'll be using to read user input from STDIN.&lt;/p&gt;

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

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;src\lib.rs&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Function Definition
&lt;/h2&gt;

&lt;p&gt;Let's go ahead and create the function definition. We'll call it &lt;strong&gt;get_input&lt;/strong&gt; as well.&lt;/p&gt;

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

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_input&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;src\lib.rs&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://doc.rust-lang.org/std/keyword.pub.html" rel="noopener noreferrer"&gt;pub&lt;/a&gt; stands for 'public' because we are allowing others to use our &lt;strong&gt;get_input&lt;/strong&gt; function. Rust's functions and other objects are usually private by default, which means that we have to explicitly mark them as public before outside code can call into them.&lt;/p&gt;

&lt;p&gt;For now, our function doesn't take any input parameters, neither does it return any output.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading Input from STDIN
&lt;/h2&gt;

&lt;p&gt;Remember that we want our function to read user input from STDIN. This is where the previously imported IO module comes into play.&lt;/p&gt;

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

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

    &lt;span class="c1"&gt;// Reads the input from STDIN and places it in the String named input.&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Enter a value:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.read_line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to read input."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"'{}'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;In the above, we declare a new String variable named &lt;strong&gt;input&lt;/strong&gt; and use the &lt;strong&gt;Stdin&lt;/strong&gt; struct's &lt;strong&gt;read_line&lt;/strong&gt; method to place the collected input into it. The &lt;strong&gt;expect&lt;/strong&gt; method allows us to display a message on encountering an error, before crashing the program. This is called &lt;a href="https://doc.rust-lang.org/std/macro.panic.html" rel="noopener noreferrer"&gt;panicking&lt;/a&gt; in Rust. On the last line, we print the collected input for illustrative purposes.&lt;/p&gt;

&lt;p&gt;To call our library, create a &lt;code&gt;main.rs&lt;/code&gt; file (which is a binary crate root as opposed to &lt;code&gt;lib.rs'&lt;/code&gt; library crate root) in the &lt;code&gt;src&lt;/code&gt; directory, right alongside &lt;code&gt;lib.rs&lt;/code&gt; like so:&lt;/p&gt;

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

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;get_input&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;get_input&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;get_input&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;src\main.rs&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In the above, we import the &lt;strong&gt;get_input&lt;/strong&gt; function from our &lt;code&gt;get_input&lt;/code&gt; library crate and call it from &lt;code&gt;main.rs'&lt;/code&gt; main function. To run the program, execute &lt;code&gt;cargo run&lt;/code&gt; in the &lt;code&gt;get_input&lt;/code&gt; project directory. &lt;/p&gt;

&lt;p&gt;Enter 23 into the terminal, and the result should be similar to the below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1620920741059%2FPndDi9dYf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1620920741059%2FPndDi9dYf.png" alt="Untitled.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that the closing quote is on a new line. This is because of the newline character (&lt;code&gt;\n&lt;/code&gt;) appended when we read from STDIN. We'll need to remove this before we can convert our input to other types.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;trim&lt;/strong&gt; method from the standard library trims leading and trailing whitespace, and this includes the newline character:&lt;/p&gt;

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

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

    &lt;span class="c1"&gt;// Reads the input from STDIN and places it in the String named input.&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Enter a value:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.read_line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to read input."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="nf"&gt;.trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nd"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"'{}'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;src\lib.rs&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Running the above should produce the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1620920762967%2FEhVtajTJ9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1620920762967%2FEhVtajTJ9.png" alt="Untitled 1.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Much better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Converting Strings to Other types
&lt;/h2&gt;

&lt;p&gt;Rust's &lt;a href="https://doc.rust-lang.org/std/primitive.str.html#method.parse" rel="noopener noreferrer"&gt;parse&lt;/a&gt; is a useful method that parses a string slice into another type. Using this, we can trivially convert our collected input into an integer, for example.&lt;/p&gt;

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

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

    &lt;span class="c1"&gt;// Reads the input from STDIN and places it in the String named input.&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Enter a value:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.read_line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to read input."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Convert to an i32.&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="nf"&gt;.trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nd"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"'{}'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;src\lib.rs&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In the above, we use type annotation to specify that we want the &lt;strong&gt;parse&lt;/strong&gt; method to convert our input to an i32. We use the &lt;strong&gt;unwrap&lt;/strong&gt; method because &lt;strong&gt;parse&lt;/strong&gt; returns a &lt;a href="https://doc.rust-lang.org/std/result/enum.Result.html" rel="noopener noreferrer"&gt;Result&lt;/a&gt; type. This is a compound type that represents either success or failure of an operation. You can read more about Result by clicking that link. &lt;strong&gt;unwrap&lt;/strong&gt; allows us to access the underlying value if the operation was successful. If it wasn't, it panics.&lt;/p&gt;

&lt;p&gt;Run the program again and input 23 once again:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1620920835360%2F1FJiS7xd4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1620920835360%2F1FJiS7xd4.png" alt="Untitled 2.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The usefulness of parsing might not be immediately apparent, but this conversion means that we can now perform integer maths with it:&lt;/p&gt;

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

&lt;span class="c1"&gt;// Same as above&lt;/span&gt;

&lt;span class="nd"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"'{}'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;src\lib.rs&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In the above, we multiply the input-String-turned-integer by three.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1620920851547%2FAyLhpcwHP.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1620920851547%2FAyLhpcwHP.png" alt="Untitled 3.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Error handling using match
&lt;/h2&gt;

&lt;p&gt;We can convert to integers and multiply them, excellent. But what happens when we enter input that isn't easily converted to an integer?&lt;/p&gt;

&lt;p&gt;We get this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1620920867217%2FPdV09f4hS.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1620920867217%2FPdV09f4hS.png" alt="Untitled 4.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above, the highlighted part of the error message clues us into its cause: &lt;strong&gt;parse&lt;/strong&gt; failed to convert the input "dev.to" into an integer, and it proceeded to panic because we used &lt;strong&gt;unwrap&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;There are a number of ways to better handle this error. One method is using &lt;code&gt;match&lt;/code&gt; and &lt;code&gt;loop&lt;/code&gt;. This provides pattern-matching control flow while making sure the user enters valid input before exiting the loop. Let's add a loop-match implementation to &lt;strong&gt;get_input&lt;/strong&gt;:&lt;/p&gt;

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

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_input&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

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

        &lt;span class="c1"&gt;// Reads the input from STDIN and places it in the String named input.&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Enter a value:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.read_line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to read input."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Convert to an i32.&lt;/span&gt;
        &lt;span class="c1"&gt;// If successful, bind to a new variable named input.&lt;/span&gt;
        &lt;span class="c1"&gt;// If failed, restart the loop.&lt;/span&gt;
          &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="nf"&gt;.trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="py"&gt;.parse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parsed_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parsed_input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="nd"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"'{}'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;src\lib.rs&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In the above, we place the contents of the function body into Rust's infinite loop implementation: &lt;code&gt;loop&lt;/code&gt;. This ensures the loop doesn't end unless we use the corresponding &lt;code&gt;break&lt;/code&gt; keyword.&lt;/p&gt;

&lt;p&gt;Back to the input trimming and parsing code block, there are a few things going on here. We use the &lt;code&gt;let&lt;/code&gt; keyword to &lt;a href="https://en.wikipedia.org/wiki/Variable_shadowing" rel="noopener noreferrer"&gt;shadow&lt;/a&gt; the previously-declared String variable &lt;strong&gt;input&lt;/strong&gt; with a new one of our desired type: i32.&lt;/p&gt;

&lt;p&gt;We then use &lt;code&gt;match&lt;/code&gt; to pattern-match the output of the trimming and parsing. Remember that &lt;strong&gt;parse&lt;/strong&gt; returns a Result type? We can then use &lt;code&gt;match&lt;/code&gt; to address Result's possible variants, which are two in number. The &lt;strong&gt;Ok(value)&lt;/strong&gt; variant indicates success, and it contains the successfully parsed value. &lt;strong&gt;Err(error)&lt;/strong&gt; on the other hand contains the information on the error encountered.&lt;/p&gt;

&lt;p&gt;Match's arms can be read from left to right. On the left side are the possible scenarios/cases, called &lt;strong&gt;match arms&lt;/strong&gt;, and on the right side are the conditional code blocks to be run. &lt;/p&gt;

&lt;p&gt;In summary, we've told the match expression to evaluate the return value of trimming and parsing the String input, then bind the trimmed &amp;amp; parsed output to the variable &lt;strong&gt;input&lt;/strong&gt; if successful. If the operation is not successful, i.e. if an error occurs, we've specified, via the &lt;code&gt;continue&lt;/code&gt; keyword, that the function should continue to the next iteration of the infinite loop: forever looping until the user enters valid input.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(I have never heard of Ctrl + C. What's that?)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Generalizing the function
&lt;/h2&gt;

&lt;p&gt;Now, we have a function that doesn't get bogged down by trivial things such as incorrect input. What next?&lt;/p&gt;

&lt;p&gt;Although converting Strings to integers is a useful feature for our library, we still need &lt;strong&gt;get_input&lt;/strong&gt; to convert our String input to other types. Suppose we also wanted to convert to a u32. How would we do that? We could do the following:&lt;/p&gt;

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

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_input_u32&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

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

        &lt;span class="c1"&gt;// Reads the input from STDIN and places it in the String named input.&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Enter a value:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.read_line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to read input."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Convert to a u32.&lt;/span&gt;
        &lt;span class="c1"&gt;// If successful, bind to a new variable named input.&lt;/span&gt;
        &lt;span class="c1"&gt;// If failed, restart the loop.&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="nf"&gt;.trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="py"&gt;.parse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parsed_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parsed_input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="nd"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"'{}'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;src\lib.rs&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;However, one needn't be told that this would soon become quite tedious. A better solution would be to utilize Rust's useful &lt;strong&gt;generics&lt;/strong&gt;. This would allow us to convert into many types without duplicating code. &lt;/p&gt;

&lt;p&gt;Let's modify &lt;strong&gt;get_input&lt;/strong&gt; to take advantage of generics. We'll also modify the function so it now returns output:&lt;/p&gt;

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

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;get_input&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;U&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;str&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FromStr&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;U&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

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

        &lt;span class="c1"&gt;// Reads the input from STDIN and places it in the String named input.&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Enter a value:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.read_line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to read input."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Convert to another type.&lt;/span&gt;
        &lt;span class="c1"&gt;// If successful, bind to a new variable named input.&lt;/span&gt;
        &lt;span class="c1"&gt;// If failed, restart the loop.&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="nf"&gt;.trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="py"&gt;.parse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;U&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parsed_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parsed_input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;src\lib.rs&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In the above, we introduce generics in our function. This allows us to convert to any type that implements the &lt;strong&gt;FromStr&lt;/strong&gt; trait bound. Trait bounds allow us specify exactly what types of values can be substituted by the generic &lt;strong&gt;U&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;FromStr&lt;/strong&gt; Trait, in particular, is implemented by types that can be constructed from a String. This, thankfully, includes the primitive types. &lt;/p&gt;

&lt;p&gt;With trait bounds, we're saying: "you can only substitute &lt;strong&gt;U&lt;/strong&gt; for any type that implements &lt;strong&gt;FromStr&lt;/strong&gt;".&lt;/p&gt;

&lt;p&gt;Notice that we've altered the return type of the function as well. Now, we specify that &lt;strong&gt;get_input&lt;/strong&gt; should only parse and return, by way of the generic &lt;strong&gt;U&lt;/strong&gt;, any type that implements &lt;strong&gt;FromStr&lt;/strong&gt; as previously discussed.&lt;/p&gt;

&lt;p&gt;Over in &lt;code&gt;main.rs&lt;/code&gt;, we modify our caller to take advantage of the flexibility provided by generics:&lt;/p&gt;

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

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;get_input&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;get_input&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_input&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nd"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"'{}'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;src\main.rs&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We use type annotation to specify that we want an i32 returned. This means that &lt;strong&gt;get_input&lt;/strong&gt; will substitute i32 for the previously-mentioned generic &lt;strong&gt;U&lt;/strong&gt; in this case. We can also just as easily ask for a u32 or an isize simply by changing the type annotation.&lt;/p&gt;

&lt;h1&gt;
  
  
  Extra Functionality
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Custom Prompts
&lt;/h2&gt;

&lt;p&gt;Now that we've implemented our small library's core functionality, we're ready to move on to some extras. Now, we want &lt;strong&gt;get_input&lt;/strong&gt; to display custom prompts when asking for user input, instead of the default "Enter a value:". We can achieve this by modifying the function definition to accept parameters:&lt;/p&gt;

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

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;get_input&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;U&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;str&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FromStr&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;U&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

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

        &lt;span class="c1"&gt;// Reads the input from STDIN and places it in the String named input.&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.read_line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to read input."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Convert to another type.&lt;/span&gt;
        &lt;span class="c1"&gt;// If successful, bind to a new variable named input.&lt;/span&gt;
        &lt;span class="c1"&gt;// If failed, restart the loop.&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="nf"&gt;.trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="py"&gt;.parse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;U&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parsed_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parsed_input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;src\lib.rs&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In the above, we've made it so that &lt;strong&gt;get_input&lt;/strong&gt; accepts input in form of a string slice, and displays it to the user before asking for input.&lt;/p&gt;

&lt;h2&gt;
  
  
  Having STDIN on the Same Line as STDOUT
&lt;/h2&gt;

&lt;p&gt;Using functionality provided by the &lt;strong&gt;Write&lt;/strong&gt; trait, we can display the input and output streams on the same line like in the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1620920890978%2F3KuhbQ8JB.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1620920890978%2F3KuhbQ8JB.png" alt="Untitled 5.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can achieve that by flushing STDOUT&lt;a href="https://stackoverflow.com/questions/54262976/how-do-i-print-stdout-and-get-stdin-on-the-same-line-in-rust" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;:&lt;/p&gt;

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

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;get_input&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;U&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;str&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FromStr&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;U&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

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

        &lt;span class="c1"&gt;// Reads the input from STDIN and places it in the String named input.&lt;/span&gt;
        &lt;span class="nd"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to flush stdout."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

        &lt;span class="c1"&gt;// Convert to another type.&lt;/span&gt;
        &lt;span class="c1"&gt;// If successful, bind to a new variable named input.&lt;/span&gt;
        &lt;span class="c1"&gt;// If failed, restart the loop.&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="nf"&gt;.trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="py"&gt;.parse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;U&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parsed_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parsed_input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;src\lib.rs&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In the above, we flush STDOUT so that it and STDIN can be displayed on the same line.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;There are other ways to convert string slices to other types. For example, using the &lt;strong&gt;&lt;a href="https://doc.rust-lang.org/std/str/trait.FromStr.html#tymethod.from_str" rel="noopener noreferrer"&gt;from_str&lt;/a&gt;&lt;/strong&gt; function is a common way of achieving this.&lt;/li&gt;
&lt;li&gt;The most structurally sound design decision would've been to use structs to more easily manage our code. I decided against this because this example library meets a very specific use case: the need to collect and parse input using a simple function. Typing &lt;code&gt;get_input("Prompt: ");&lt;/code&gt; is preferable to typing &lt;code&gt;get_input::new().with_prompt("Prompt: ").get()&lt;/code&gt; as in other more sophisticated libraries for this narrow use case.&lt;/li&gt;
&lt;li&gt;Well-documented input collection crates already exist. &lt;a href="https://doc.rust-lang.org/std/str/trait.FromStr.html#tymethod.from_str" rel="noopener noreferrer"&gt;Dialoguer&lt;/a&gt; and &lt;a href="https://crates.io/crates/read_input" rel="noopener noreferrer"&gt;read_input&lt;/a&gt; are two great libraries that come to mind.&lt;/li&gt;
&lt;li&gt;Rust's Book is the definitive introduction to Rust. &lt;a href="https://doc.rust-lang.org/book/" rel="noopener noreferrer"&gt;Here's a link&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rust</category>
      <category>beginners</category>
      <category>linux</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
