<?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>Forem: Jeff Culverhouse</title>
    <description>The latest articles on Forem by Jeff Culverhouse (@jculverhouse).</description>
    <link>https://forem.com/jculverhouse</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%2F206946%2Fb1d8cf4e-b197-47e3-93ba-751ed49cd278.jpg</url>
      <title>Forem: Jeff Culverhouse</title>
      <link>https://forem.com/jculverhouse</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jculverhouse"/>
    <language>en</language>
    <item>
      <title>Some(number) of ways to calculate a Fibonacci Number in Rust</title>
      <dc:creator>Jeff Culverhouse</dc:creator>
      <pubDate>Wed, 22 Jul 2020 21:15:49 +0000</pubDate>
      <link>https://forem.com/jculverhouse/some-number-of-ways-to-calculate-a-fibonacci-number-in-rust-d78</link>
      <guid>https://forem.com/jculverhouse/some-number-of-ways-to-calculate-a-fibonacci-number-in-rust-d78</guid>
      <description>&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Golden_ratio" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi1.wp.com%2Frust.graystorm.com%2Fwp-content%2Fuploads%2F2020%2F07%2Fsea-spiral-animal-red-holiday-memory-1255334-pxhere.com_.jpg%3Fw%3D840%26ssl%3D1" alt="A Fibonacci spiral found in nature, in a nautilus shell."&gt;&lt;/a&gt;A Fibonacci number divided by the previous one approaches Phi, the &lt;a href="https://en.wikipedia.org/wiki/Golden_ratio" rel="noreferrer noopener"&gt;Golden Ratio&lt;/a&gt;. That’s an Internet hole that can last for hours, if you let it! However, &lt;a href="https://en.wikipedia.org/wiki/Golden_ratio#Disputed_observations" rel="noreferrer noopener"&gt;don’t believe everything&lt;/a&gt; you read about Phi.&lt;/p&gt;

&lt;p&gt;Solving Fibonacci Numbers is the start of Chapter 3 on Dynamic Programming (more on that below) in Erickson’s &lt;a href="http://jeffe.cs.illinois.edu/teaching/algorithms/" rel="noopener noreferrer"&gt;Algorithm&lt;/a&gt; book. I had started with &lt;a href="https://rust.graystorm.com/2020/07/14/algorithmic-rust/" rel="noopener noreferrer"&gt;Peasant Multiplication&lt;/a&gt;, then the &lt;a href="https://rust.graystorm.com/2020/07/15/merge-sort-with-rust/" rel="noopener noreferrer"&gt;merge sort&lt;/a&gt;, and most fun – the &lt;a href="https://rust.graystorm.com/2020/07/16/next-algorithm-backtracking-into-the-n-queens-problem/" rel="noopener noreferrer"&gt;n Queens Problem&lt;/a&gt;. With Fibonacci Number calculating though, there are a couple of obvious ways to code this and some presented questions for me with Rust.&lt;/p&gt;

&lt;p&gt;I became interested in comparing a couple of these ways – both in thinking about the Rust code and looking at the timing. Then my eyes popped out when I saw the difference in the release build times!&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%2Fi0.wp.com%2Frust.graystorm.com%2Fwp-content%2Fuploads%2F2020%2F07%2FScreen-Shot-2020-07-22-at-5.08.27-PM.png%3Fw%3D840%26ssl%3D1" 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%2Fi0.wp.com%2Frust.graystorm.com%2Fwp-content%2Fuploads%2F2020%2F07%2FScreen-Shot-2020-07-22-at-5.08.27-PM.png%3Fw%3D840%26ssl%3D1"&gt;&lt;/a&gt;&lt;em&gt;Pseudo code, Page 97 from Algorithm by Jeff Erickson&lt;/em&gt;&lt;br&gt;Clean, Simple Recursion&lt;br&gt;&lt;/p&gt;

&lt;p&gt;First is probably closest to the pseudo code for the classic solution for Fibonacci. Define what 0 and 1 return and solve for the given number, recursing all the way back to 2 (which adds the fixed answers for 0 and 1):&lt;/p&gt;

&lt;h2&gt;
  
  
  Recursive Backtracing
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fn backtrace_fib(fib_num: u128) -&amp;gt; u128 {
    if fib_num == 0 || fib_num == 1 {
        return fib_num;
    }
    backtrace_fib(fib_num - 1) + backtrace_fib(fib_num - 2)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, especially important if your function will be called multiple times, is to add memoization. That is, once you calculate an answer for a given input, remember than answer so you can quickly respond with it later, skipping the math.&lt;/p&gt;

&lt;p&gt;I don’t like that, with the way I did this, I have to pass in my HashMap where I’m storing the answers. Is there any way to have some 'static living private variable that only this function would see, but would last the whole run of the program?? There are other places I could store away data, like memcache and redis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Backtracing With Memoization
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fn backtrace_memo_fib(memo: &amp;amp;mut HashMap&amp;lt;u128, u128&amp;gt;, fib_num: u128) -&amp;gt; u128 {
    match memo.get(&amp;amp;fib_num).map(|answer| answer.clone()) {
        Some(result) =&amp;gt; result,
        None =&amp;gt; {
            let result = match fib_num {
                0 | 1 =&amp;gt; fib_num,
                n =&amp;gt; backtrace_memo_fib(memo, n - 1) + backtrace_memo_fib(memo, n - 2),
            };
            memo.insert(fib_num, result.clone());
            result
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, Jeff Erickson, author of the &lt;a href="http://jeffe.cs.illinois.edu/teaching/algorithms/" rel="noopener noreferrer"&gt;Algorithms&lt;/a&gt; book, explains another way solve for a Fibonacci Number involves using dynamic programming. But this IS your grandfathers “programming” (not ours).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The word 'programming' does not refer to writing code, but rather to the older sense of &lt;em&gt;planning&lt;/em&gt; or &lt;em&gt;scheduling&lt;/em&gt;, typically by filling in a table. For example, sports programs and theater programs are schedules of important events (with ads); television programming involves filling each available time slot with a show (and ads); degree programs are schedules of classes to be taken (with ads).&lt;/p&gt;

&lt;p&gt;&lt;cite&gt;Erickson, Jeff (2018, December 29). Algorithms. pp. 100. Retrieved from Algorithms: &lt;a href="http://algorithms.wtf" rel="noopener noreferrer"&gt;http://algorithms.wtf&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For this one, I just kept the memoization inside the function. We then purposely fill the HashMap on our way up, referencing already-calculated answers, and so never descend into levels of recursion.&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%2Fi0.wp.com%2Frust.graystorm.com%2Fwp-content%2Fuploads%2F2020%2F07%2FScreen-Shot-2020-07-22-at-5.08.47-PM-1.png%3Fw%3D840%26ssl%3D1" 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%2Fi0.wp.com%2Frust.graystorm.com%2Fwp-content%2Fuploads%2F2020%2F07%2FScreen-Shot-2020-07-22-at-5.08.47-PM-1.png%3Fw%3D840%26ssl%3D1"&gt;&lt;/a&gt;&lt;em&gt;Pseudo code, Page 99 from Algorithm by Jeff Erickson&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Dynamic Programming
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fn dynamic_fib(fib_num: u128) -&amp;gt; u128 {
    let mut memo = HashMap::new();
    memo.insert(0, 0);
    memo.insert(1, 1);
    match fib_num {
        0 | 1 =&amp;gt; {} // already set
        n =&amp;gt; {
            for i in 2..=n {
                let result = *memo.get(&amp;amp;(i - 1)).unwrap() + *memo.get(&amp;amp;(i - 2)).unwrap();
                memo.insert(i, result);
            }
        }
    };
    *memo.get(&amp;amp;fib_num).unwrap()
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, as I was trying to figure out how to store some data in a function for future calls (if that is even possible), I came across the &lt;a href="http://cached%20=%20%220.16.0%22" rel="noopener noreferrer"&gt;cached crate&lt;/a&gt;. “&lt;code&gt;cached&lt;/code&gt; provides implementations of several caching structures as well as a handy macro for defining memoized functions.” How interesting – just what I needed and the memoization is even hidden from ME. Ok, I’ll do the simple, recursive, backtracing function but cache the results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cached Backtracing Function
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#[cached(size = 200)]
fn cached_fib(fib_num: u128) -&amp;gt; u128 {
    if fib_num == 0 || fib_num == 1 {
        return fib_num;
    }
    cached_fib(fib_num - 1) + cached_fib(fib_num - 2)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Fibonacci Fight
&lt;/h2&gt;

&lt;p&gt;So, I wrap all of those up into main() so I can start comparing them. That code is pretty boring, so check it out in the repo. Mostly I run each flavor of the algorithm, timing the result and print it all out. The first one looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    let now = Instant::now();
    let _ = backtrace_fib(fib_num);
    let elapsed = now.elapsed();
    print_results(fib_num, "simple backtracing/recursion", elapsed);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also added a test, just to be sure each is giving the correct answer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#[test]
fn test_each_version() {
    assert_eq!(backtrace_fib(20), 6765);
    assert_eq!(backtrace_memo_fib(&amp;amp;mut HashMap::new(), 20), 6765);
    assert_eq!(dynamic_fib(20), 6765);
    assert_eq!(cached_fib(20), 6765);
}

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Fibonacci Racing
&lt;/h2&gt;

&lt;p&gt;And then some code to time each version, and call it a second and third time, so we can see the memoization at work.&lt;/p&gt;

&lt;p&gt;Of course, your results will vary by CPU, but look at this run for Fibonacci Number 50 with the debug build (where the differences are huge). This is on an Amazon t2.medium EC2 server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The first time solving will be the slowest

  Solving fib:50 with simple backtracing/recursion                       took    287244288946 ns
  Solving fib:50 with backtracing/recursion with memoization             took          211289 ns
  Solving fib:50 with dynamic programming with memoization               took          167291 ns
  Solving fib:50 with cached function                                    took          214175 ns

What about solving it a second or third time, anyone faster this time?

  Solving fib:50 with simple backtracing/recursion                       took    287262389809 ns
  Solving fib:50 with backtracing/recursion with memoization             took          202481 ns
  Solving fib:50 with dynamic programming with memoization               took          162527 ns
  Solving fib:50 with cached function                                    took            6285 ns

  Solving fib:50 with simple backtracing/recursion                       took    287273113221 ns
  Solving fib:50 with backtracing/recursion with memoization             took          185609 ns
  Solving fib:50 with dynamic programming with memoization               took          158492 ns
  Solving fib:50 with cached function                                    took            6496 ns

By the way, Fibonacci Number 50 is 12586269025 which (divided by Fib Num 49) approxmates phi as 1.618033988749895
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But wow, check out these numbers with a release build!!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The first time solving will be the slowest

  Solving fib:50 with simple backtracing/recursion                       took             806 ns
  Solving fib:50 with backtracing/recursion with memoization             took           16128 ns
  Solving fib:50 with dynamic programming with memoization               took            8052 ns
  Solving fib:50 with cached function                                    took           19495 ns

What about solving it a second or third time, anyone faster this time?

  Solving fib:50 with simple backtracing/recursion                       took             596 ns
  Solving fib:50 with backtracing/recursion with memoization             took            8142 ns
  Solving fib:50 with dynamic programming with memoization               took            7576 ns
  Solving fib:50 with cached function                                    took             724 ns

  Solving fib:50 with simple backtracing/recursion                       took             596 ns
  Solving fib:50 with backtracing/recursion with memoization             took            7549 ns
  Solving fib:50 with dynamic programming with memoization               took            7327 ns
  Solving fib:50 with cached function                                    took             746 ns

By the way, Fibonacci Number 50 is 12586269025 which (divided by Fib Num 49) approxmates phi as 1.618033988749895
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A Really Big Number
&lt;/h2&gt;

&lt;p&gt;And it handles a Fibonacci Number of 186, though any higher and casting the answers as &lt;strong&gt;f64&lt;/strong&gt; s to divide and get Phi breaks. The fastest “first” calculation for Fibonacci Number 186 was &lt;strong&gt;simple backtracing/recursion&lt;/strong&gt; and took only 820 ns and it’s kinda big:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;By the way, Fibonacci Number 186 is 332825110087067562321196029789634457848 which (divided by Fib Num 185) approximates phi as 1.6180339887498947
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The post &lt;a href="https://rust.graystorm.com/2020/07/22/somenumber-of-ways-to-calculate-a-fibonacci-number-in-rust/" rel="noopener noreferrer"&gt;Some(number) of ways to calculate a Fibonacci Number in Rust&lt;/a&gt; appeared first on &lt;a href="https://rust.graystorm.com" rel="noopener noreferrer"&gt;Learning Rust&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>crates</category>
      <category>learning</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>(A Few) Advanced Variable Types in Rust</title>
      <dc:creator>Jeff Culverhouse</dc:creator>
      <pubDate>Mon, 20 Jul 2020 22:26:28 +0000</pubDate>
      <link>https://forem.com/jculverhouse/a-few-advanced-variable-types-in-rust-3n2a</link>
      <guid>https://forem.com/jculverhouse/a-few-advanced-variable-types-in-rust-3n2a</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cdUWcjX9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i2.wp.com/rust.graystorm.com/wp-content/uploads/2020/07/laptop-computer-macbook-writing-hand-working-891776-pxhere.com_.jpg%3Fw%3D840%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cdUWcjX9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i2.wp.com/rust.graystorm.com/wp-content/uploads/2020/07/laptop-computer-macbook-writing-hand-working-891776-pxhere.com_.jpg%3Fw%3D840%26ssl%3D1" alt="Programmer on laptop, presumably trying to figure out how to get access to his variable in several threads of his Rust program."&gt;&lt;/a&gt;Keep one eye on your code at all times!&lt;/p&gt;

&lt;p&gt;“I haven’t seen &lt;em&gt;Evil Dead II&lt;/em&gt; yet”. Much is made about this simple question in the movie adaption of &lt;em&gt;[High Fidelity](&lt;a href="https://en.wikipedia.org/wiki/High_Fidelity"&gt;https://en.wikipedia.org/wiki/High_Fidelity&lt;/a&gt;&lt;/em&gt;(film))_. Does “yet” mean the person does, indeed, intend to see the film? Jack Black’s character is having real trouble with the concept – not only does he know that the speaker, John Cusack’s character, has seen &lt;a href="https://en.wikipedia.org/wiki/High_Fidelity_(film)"&gt;Evil Dead II&lt;/a&gt;, but what idiot wouldn’t see it, “&lt;a href="https://en.wikiquote.org/wiki/High_Fidelity_(film)#:~:text=Barry%3A%20Because%20it's%20a%20brilliant%20film"&gt;because&lt;/a&gt; it’s a brilliant film. It’s so funny, and violent, and the soundtrack kicks so much ass.” I love this exchange, but I’m a fan of the film anyway. It is not always clear to me how to handle advanced variable types Rust, yet.   &lt;/p&gt;

&lt;p&gt;I think of these as wrappers that add abilities (and restrictions) to a variable. They give a variable super powers since the Rust compiler is so strict about what you can and can’t do with variables.&lt;/p&gt;




&lt;h2&gt;
  
  
  Box&amp;lt;T&amp;gt;
&lt;/h2&gt;

&lt;p&gt;PROVIDES:&lt;br&gt;&lt;br&gt;
Smart pointer that forces your variable’s value to be stored on the heap instead of the stack. The &lt;strong&gt;Box&amp;lt;&amp;gt;&lt;/strong&gt; variable itself is just a pointer so its size is obvious and can, itself, be stored on the stack.  &lt;/p&gt;

&lt;p&gt;RESTRICTIONS:  &lt;/p&gt;

&lt;p&gt;USEFUL WHEN:&lt;br&gt;&lt;br&gt;
If the size of an item cannot be determined at compile time it will complain if the default is to store it on the stack (where a calculable size is necessary). Using &lt;strong&gt;Box&amp;lt;&amp;gt;&lt;/strong&gt; will force the storage on the heap where a fixed size is not needed. For example, a recursive data-structure, including enums, will not work on the stack because a concrete size cannot be calculated. Turning the recursive field into a &lt;strong&gt;Box&amp;lt;&amp;gt;&lt;/strong&gt; means it stores a pointer which CAN be sized. The example in the docs being:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;enum List\&amp;lt;T\&amp;gt; {
  Cons(T, Box\&amp;lt;List\&amp;lt;T\&amp;gt;\&amp;gt;),
  Nil,
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Also useful if you have a very large-sized T, and want to transfer ownership of that variable without it being copied each time.  &lt;/p&gt;

&lt;p&gt;NOTABLY PROVIDES:&lt;br&gt;&lt;br&gt;
just see the rust-lang.org &lt;a href="https://doc.rust-lang.org/std/boxed/index.html"&gt;docs&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;EXAMPLES/DISCUSSION:&lt;br&gt;&lt;br&gt;
&lt;a href="https://doc.rust-lang.org/stable/rust-by-example/std/box.html"&gt;https://doc.rust-lang.org/stable/rust-by-example/std/box.html&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.koderhq.com/tutorial/rust/smart-pointer/"&gt;https://www.koderhq.com/tutorial/rust/smart-pointer/&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://manishearth.github.io/blog/2017/01/10/rust-tidbits-box-is-special/"&gt;https://manishearth.github.io/blog/2017/01/10/rust-tidbits-box-is-special/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Setting the value of a simple &lt;strong&gt;Box&amp;lt;&amp;gt;&lt;/strong&gt; variable is easy enough and getting the value back looks very normal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fn main() {
  let answer = Box::new(42);
  println!("The answer is : {}", answer);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Cell&amp;lt;T&amp;gt;
&lt;/h2&gt;

&lt;p&gt;PROVIDES:&lt;br&gt;&lt;br&gt;
You can have multiple, shared references to the &lt;strong&gt;Cell&amp;lt;&amp;gt;&lt;/strong&gt; (and thus, access to the value inside with &lt;strong&gt;.get()&lt;/strong&gt;) and yet still mutate the value inside (with &lt;strong&gt;.set()&lt;/strong&gt;). This is called &lt;em&gt;interior mutability&lt;/em&gt; because the value inside can be changed but &lt;strong&gt;mut&lt;/strong&gt; on the &lt;strong&gt;Cell&amp;lt;&amp;gt;&lt;/strong&gt; itself is not needed. The inner value can &lt;em&gt;only&lt;/em&gt; be set by calling a method on the &lt;strong&gt;Cell&amp;lt;&amp;gt;&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;RESTRICTIONS:&lt;br&gt;&lt;br&gt;
It is not possible to get a reference to what is &lt;em&gt;inside&lt;/em&gt; the &lt;strong&gt;Cell&lt;/strong&gt; , only a copy of the value. Also, &lt;strong&gt;Cell&lt;/strong&gt; does not implement &lt;strong&gt;sync&lt;/strong&gt; , so it cannot be given to a different thread, which ensures safety.  &lt;/p&gt;

&lt;p&gt;USEFUL WHEN:&lt;br&gt;&lt;br&gt;
Usually used for small values, such as counters or flags, where you need multiple shared references to the value AND be allowed to mutate it at the same time, in a guaranteed safe way.  &lt;/p&gt;

&lt;p&gt;NOTABLY PROVIDES:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;.set()&lt;/strong&gt; to set the value inside&lt;br&gt;&lt;br&gt;
&lt;strong&gt;.get()&lt;/strong&gt; to get a copy of the value inside&lt;br&gt;&lt;br&gt;
&lt;strong&gt;.take()&lt;/strong&gt; to get a copy of the value inside AND reset the value inside to default.&lt;br&gt;&lt;br&gt;
see the rust-lang.org &lt;a href="https://doc.rust-lang.org/std/cell/"&gt;docs&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;EXAMPLES/DISCUSSION:&lt;br&gt;&lt;br&gt;
&lt;a href="https://hub.packtpub.com/shared-pointers-in-rust-challenges-solutions/"&gt;https://hub.packtpub.com/shared-pointers-in-rust-challenges-solutions/&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://ricardomartins.cc/2016/06/08/interior-mutability"&gt;https://ricardomartins.cc/2016/06/08/interior-mutability&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;Setting the inner value of a &lt;strong&gt;Cell&amp;lt;&amp;gt;&lt;/strong&gt; is only possible with a method call which is how it maintains safety:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use std::cell::Cell;
fn main() {
  let answer = Cell::new(0);
  answer.set(42);
  println!("The answer is : {}", answer.get());
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;






&lt;h2&gt;
  
  
  RefCell&amp;lt;T&amp;gt;
&lt;/h2&gt;

&lt;p&gt;PROVIDES:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;RefCell&amp;lt;&amp;gt;&lt;/strong&gt; is very similar to &lt;strong&gt;Cell&amp;lt;&amp;gt;&lt;/strong&gt; except it adds borrow checking, but at run-time instead of compile time! This means, unlike &lt;strong&gt;Cell&amp;lt;&amp;gt;&lt;/strong&gt; , it is possible to write &lt;strong&gt;RefCell&amp;lt;&amp;gt;&lt;/strong&gt; code which will &lt;strong&gt;panic!()&lt;/strong&gt;. You &lt;strong&gt;borrow()&lt;/strong&gt; a ref to the inner value for read-only or &lt;strong&gt;borrow_mut()&lt;/strong&gt; in order to change it.  &lt;/p&gt;

&lt;p&gt;RESTRICTIONS:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;borrow()&lt;/strong&gt; will panic if a &lt;strong&gt;borrow_mut()&lt;/strong&gt; is in place, and &lt;strong&gt;borrow_mut()&lt;/strong&gt; will panic if either type is in place.  &lt;/p&gt;

&lt;p&gt;USEFUL WHEN:  &lt;/p&gt;

&lt;p&gt;NOTABLY PROVIDES:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;.borrow()&lt;/strong&gt; to get a copy of the value at the ref&lt;br&gt;&lt;br&gt;
&lt;strong&gt;.borrow_mut()&lt;/strong&gt; to set the value at the ref&lt;br&gt;&lt;br&gt;
&lt;strong&gt;.try_borrow()&lt;/strong&gt; and &lt;strong&gt;.try_borrow_mut()&lt;/strong&gt; will return a &lt;strong&gt;Result&amp;lt;&amp;gt;&lt;/strong&gt; or error instead of a &lt;strong&gt;panic!()&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
see the rust-lang.org &lt;a href="https://doc.rust-lang.org/std/cell/struct.RefCell.html"&gt;docs&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;EXAMPLES/DISCUSSION:&lt;br&gt;&lt;br&gt;
&lt;a href="https://ricardomartins.cc/2016/06/08/interior-mutability"&gt;https://ricardomartins.cc/2016/06/08/interior-mutability&lt;/a&gt; (again)  &lt;/p&gt;

&lt;p&gt;You must successfully &lt;strong&gt;borrow_mut()&lt;/strong&gt; the &lt;strong&gt;RefCell&amp;lt;&amp;gt;&lt;/strong&gt; in order to set the value (by dereferencing) and then simply &lt;strong&gt;borrow()&lt;/strong&gt; it to retrieve the value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use std::cell::RefCell;
fn main() {
  let answer = RefCell::new(0);
  *answer.borrow_mut() = 42;
  println!("The answer is : {}", answer.borrow());
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;whereas, something as simple as this compiles, but panics at run-time. Imagine how much more obscure this code could be. Remember, any number of read-only references or exactly 1 read-write reference and nothing else – although for RefCell, this is enforced at run-time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use std::cell::RefCell;
fn main() {
  let answer = RefCell::new(0);
  let break_things = answer.borrow_mut();
  println!("The initial value is : {}", *break_things); 
  *answer.borrow_mut() = 42;
  println!("The answer is : {}", answer.borrow());
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Rc&amp;lt;T&amp;gt;
&lt;/h2&gt;

&lt;p&gt;PROVIDES:&lt;br&gt;&lt;br&gt;
Adds the feature of run-time reference counting to your variable, but this is the simple, lower-cost version – it is not thread safe.  &lt;/p&gt;

&lt;p&gt;RESTRICTIONS:&lt;br&gt;&lt;br&gt;
Right from the docs “you cannot generally obtain a mutable reference to something inside an &lt;a href="https://doc.rust-lang.org/std/rc/struct.Rc.html"&gt;&lt;code&gt;Rc&lt;/code&gt;&lt;/a&gt;. If you need mutability, put a &lt;a href="https://doc.rust-lang.org/std/cell/struct.Cell.html"&gt;&lt;code&gt;Cell&lt;/code&gt;&lt;/a&gt; or &lt;a href="https://doc.rust-lang.org/std/cell/struct.RefCell.html"&gt;&lt;code&gt;RefCell&lt;/code&gt;&lt;/a&gt; inside the &lt;code&gt;Rc&lt;/code&gt;“. So while there is a &lt;strong&gt;get_mut()&lt;/strong&gt; method, it’s easy to just use a &lt;strong&gt;Cell&amp;lt;&amp;gt;&lt;/strong&gt; inside.  &lt;/p&gt;

&lt;p&gt;USEFUL WHEN:&lt;br&gt;&lt;br&gt;
You need run-time reference counting of a variable so it hangs around until the last reference of it is gone.  &lt;/p&gt;

&lt;p&gt;NOTABLY PROVIDES:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;.clone()&lt;/strong&gt; – get a new copy of the pointer to the same value, upping the reference count by 1.&lt;br&gt;&lt;br&gt;
see the rust-lang.org &lt;a href="https://doc.rust-lang.org/std/rc/"&gt;docs&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;EXAMPLES/DISCUSSION:&lt;br&gt;&lt;br&gt;
&lt;a href="https://blog.sentry.io/2018/04/05/you-cant-rust-that#refcounts-are-not-dirty"&gt;https://blog.sentry.io/2018/04/05/you-cant-rust-that#refcounts-are-not-dirty&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;Note that in the example below, &lt;em&gt;my_answer&lt;/em&gt; is still pointing to valid memory even when &lt;em&gt;correct_answer&lt;/em&gt; is dropped, because the &lt;strong&gt;Rc&amp;lt;&amp;gt;&lt;/strong&gt; had an internal count of “2” and drops it to “1”, leaving the storage of “42” still valid.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use std::rc::Rc;
fn main() {
  let correct_answer = Rc::new(42);
  let my_answer = Rc::clone(&amp;amp;correct_answer);
  println!("The correct answer is : {}", correct_answer);
  drop(correct_answer);

  println!("And you got : {}", my_answer);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;






&lt;h2&gt;
  
  
  Arc&amp;lt;T&amp;gt;
&lt;/h2&gt;

&lt;p&gt;PROVIDES:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Arc&amp;lt;&amp;gt;&lt;/strong&gt; is an atomic reference counter, very similar to &lt;strong&gt;Rc&amp;lt;&amp;gt;&lt;/strong&gt; above but thread-safe.  &lt;/p&gt;

&lt;p&gt;RESTRICTIONS:&lt;br&gt;&lt;br&gt;
More expensive than &lt;strong&gt;Rc&amp;lt;&amp;gt;&lt;/strong&gt;. Also note, the &lt;strong&gt;&amp;lt;T&amp;gt;&lt;/strong&gt; you store must have the &lt;strong&gt;Send&lt;/strong&gt; and &lt;strong&gt;Sync&lt;/strong&gt; traits. So an &lt;strong&gt;Arc&amp;lt;RefCell&amp;lt;T&amp;gt;&amp;gt;&lt;/strong&gt; will not work because &lt;strong&gt;RefCell&amp;lt;&amp;gt;&lt;/strong&gt; is not &lt;strong&gt;Sync&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;USEFUL WHEN:&lt;br&gt;&lt;br&gt;
Same as &lt;strong&gt;Rc&amp;lt;&amp;gt;&lt;/strong&gt; , You need run-time reference counting of a variable so it hangs around until the last reference of it is gone, but safe across threads as long as the inner &lt;strong&gt;&amp;lt;T&amp;gt;&lt;/strong&gt; is.  &lt;/p&gt;

&lt;p&gt;NOTABLY PROVIDES:&lt;br&gt;&lt;br&gt;
see the rust-lang.org &lt;a href="https://doc.rust-lang.org/std/sync/struct.Arc.html"&gt;docs&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;EXAMPLES/DISCUSSION:&lt;br&gt;&lt;br&gt;
&lt;a href="https://medium.com/@DylanKerler1/how-arc-works-in-rust-b06192acd0a6"&gt;https://medium.com/@DylanKerler1/how-arc-works-in-rust-b06192acd0a6&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;Same idea as with &lt;strong&gt;Rc&amp;lt;&amp;gt;&lt;/strong&gt; , we just show it working across multiple threads (and then sleep for just 10ms to let those threads finish).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use std::sync::Arc;
use std::thread;
use std::time::Duration;
fn main() {
  let answer = Arc::new(42);
  for threadno in 0..5 {
    let answer = Arc::clone(&amp;amp;answer);
    thread::spawn(move || {
      println!("Thread {}, answer is: {}", threadno + 1, answer);
    });
  }
  let ten_ms = Duration::from_millis(10);
  thread::sleep(ten_ms);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Mutex&amp;lt;T&amp;gt;
&lt;/h2&gt;

&lt;p&gt;PROVIDES:&lt;br&gt;&lt;br&gt;
Mutual exclusion lock protecting shared data, even across threads.  &lt;/p&gt;

&lt;p&gt;RESTRICTIONS:&lt;br&gt;&lt;br&gt;
Any thread which panics will “poison” the &lt;strong&gt;Mutex&amp;lt;&amp;gt;&lt;/strong&gt; and make it inaccessible to all threads. The &lt;strong&gt;T&lt;/strong&gt; stored must allow &lt;strong&gt;Send&lt;/strong&gt; but &lt;strong&gt;Sync&lt;/strong&gt; is not necessary.  &lt;/p&gt;

&lt;p&gt;USEFUL WHEN:&lt;br&gt;&lt;br&gt;
working on it!  &lt;/p&gt;

&lt;p&gt;NOTABLY PROVIDES:&lt;br&gt;&lt;br&gt;
see the rust-lang.org &lt;a href="https://doc.rust-lang.org/std/sync/struct.Mutex.html"&gt;docs&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;EXAMPLES/DISCUSSION:&lt;br&gt;&lt;br&gt;
&lt;a href="https://doc.rust-lang.org/book/ch16-03-shared-state.html"&gt;https://doc.rust-lang.org/book/ch16-03-shared-state.html&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
fn main() {
  let answer = Arc::new(Mutex::new(42));
  for thread_no in 0..5 {
    let changer = Arc::clone(&amp;amp;answer);
    thread::spawn(move || {
      let mut changer = changer.lock().unwrap();
      println!("Setting answer to thread_no: {}",
        thread_no + 1,
      );
      *changer = thread_no + 1;
    });
  }
  let ten_ms = Duration::from_millis(10);
  thread::sleep(ten_ms);
  if answer.is_poisoned() {
    println!("Mutex was poisoned :(");
  }
  else {
    println!("Mutex survived :)");
    let final_answer = answer.lock().unwrap();
    println!("Ended with answer: {}", final_answer);
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;






&lt;h2&gt;
  
  
  RwLock&amp;lt;T&amp;gt;
&lt;/h2&gt;

&lt;p&gt;PROVIDES:&lt;br&gt;&lt;br&gt;
Similar to RefCell, but thread safe. borrow() is read(), borrow_mut is write(). They don’t return an option, they will block until they do get the lock.  &lt;/p&gt;

&lt;p&gt;RESTRICTIONS:&lt;br&gt;&lt;br&gt;
Any thread which panics while a &lt;strong&gt;write&lt;/strong&gt; lock is in place will “poison” the &lt;strong&gt;RwLock&amp;lt;&amp;gt;&lt;/strong&gt; and make it inaccessible to all threads. A &lt;strong&gt;panic!&lt;/strong&gt; during a &lt;strong&gt;read&lt;/strong&gt; lock does not poison the &lt;strong&gt;RwLock&lt;/strong&gt;. The &lt;strong&gt;T&lt;/strong&gt; stored must allow both &lt;strong&gt;Send&lt;/strong&gt; and &lt;strong&gt;Sync&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;USEFUL WHEN:&lt;br&gt;&lt;br&gt;
working on it!  &lt;/p&gt;

&lt;p&gt;NOTABLY PROVIDES:&lt;br&gt;&lt;br&gt;
see the rust-lang.org &lt;a href="https://doc.rust-lang.org/std/sync/struct.RwLock.html"&gt;docs&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;EXAMPLES/DISCUSSION:  &lt;/p&gt;

&lt;p&gt;Slightly fancier example, that shows getting both &lt;strong&gt;read()&lt;/strong&gt; and &lt;strong&gt;write()&lt;/strong&gt; locks on the value. If nothing panics, we should see the answer at the end.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use std::sync::{Arc, RwLock};
use std::thread;
use std::time::Duration;
fn main() {
  let answer = Arc::new(RwLock::new(42));
  for thread_no in 0..5 {
    if thread_no % 2 == 1 {
      let changer = Arc::clone(&amp;amp;answer);
      thread::spawn(move || {
        let mut changer = changer.write().unwrap();
        println!("Setting answer to thread_no: {}",
          thread_no + 1,
        );
        *changer = thread_no + 1;
      });
    }
    else {
      let reader = Arc::clone(&amp;amp;answer);
      thread::spawn(move || {
        let reader = reader.read().unwrap();
        println!( "Checking answer in thread_no: {}, value is {}",
          thread_no + 1,
          *reader
        );
      });
    }
  }
  let ten_ms = Duration::from_millis(10);
  thread::sleep(ten_ms);
  if answer.is_poisoned() {
    println!("Mutex was poisoned :(");
  }
  else {
    println!("Mutex survived :)");
    let final_answer = answer.read().unwrap();
    println!("Ended with answer: {}", final_answer);
  }
}

Checking answer in thread_no: 1, value is 42
Checking answer in thread_no: 3, value is 42
Setting answer to thread_no: 2
Checking answer in thread_no: 5, value is 2
Setting answer to thread_no: 4
Mutex survived :)
Ended with answer: 4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;






&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;There are more, plus many custom types, some I’ve even used like the crate &lt;a href="https://docs.rs/once_cell/1.4.0/once_cell/"&gt;once_cell&lt;/a&gt;. I started using that for the web app I was (am?) working on and &lt;a href="https://rust.graystorm.com/2019/07/13/piecing-together-a-rust-web-application/"&gt;wrote a little about it&lt;/a&gt;. Also, as you saw in the last two examples, you can combine types when you need multiple functionalities. I have included these examples in a GitHub repo, &lt;a href="https://github.com/jculverhouse/pointers"&gt;pointers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I’ll probably hear about or (much more slowly) learn about mistakes I’ve made in wording here or come up with much better examples and excuses for using these various types, so I’ll try to update this post as I do. I see using this myself as a reference until I am really familiar with each of these types. Obviously, any mistakes here are mine alone as I learn Rust and not from any of the links or sources I listed!&lt;/p&gt;

&lt;p&gt;Also, lots of help from 3 YouTubers I’ve been watching – the best examples can been seen as they write code and explain why they need something inside an &lt;strong&gt;Rc&amp;lt;&amp;gt;&lt;/strong&gt; or in a &lt;strong&gt;Mutex&amp;lt;&amp;gt;&lt;/strong&gt;. Check out their streams and watch over their shoulder as they code!!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/channel/UC_iD0xppBwwsrM9DegC5cQQ"&gt;Jon Gjengset&lt;/a&gt;especially, in this case, his &lt;a href="https://www.youtube.com/watch?v=8O0Nt9qY_vo"&gt;video on this same topic&lt;/a&gt;!&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/channel/UCDmSWx6SK0zCU2NqPJ0VmDQ"&gt;David Pedersen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/channel/UCpeX4D-ArTrsqvhLapAHprQ"&gt;Ryan Levick&lt;/a&gt; who just had a &lt;a href="https://www.youtube.com/watch?v=YBG8QTO8fNI"&gt;video on once_cell&lt;/a&gt;!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The post &lt;a href="https://rust.graystorm.com/2020/07/20/a-few-advanced-variable-types-in-rust/"&gt;(A Few) Advanced Variable Types in Rust&lt;/a&gt; appeared first on &lt;a href="https://rust.graystorm.com"&gt;Learning Rust&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>learning</category>
      <category>arc</category>
      <category>box</category>
    </item>
    <item>
      <title>Next Algorithm: Backtracking into the n Queens Problem</title>
      <dc:creator>Jeff Culverhouse</dc:creator>
      <pubDate>Fri, 17 Jul 2020 02:04:19 +0000</pubDate>
      <link>https://forem.com/jculverhouse/next-algorithm-backtracking-into-the-n-queens-problem-15i9</link>
      <guid>https://forem.com/jculverhouse/next-algorithm-backtracking-into-the-n-queens-problem-15i9</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7POYaqPu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i1.wp.com/rust.graystorm.com/wp-content/uploads/2020/07/board-wood-game-play-summer-recreation-454984-pxhere.com_.jpg%3Fw%3D840%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7POYaqPu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i1.wp.com/rust.graystorm.com/wp-content/uploads/2020/07/board-wood-game-play-summer-recreation-454984-pxhere.com_.jpg%3Fw%3D840%26ssl%3D1" alt="Chessboard showing a Queen... how would you function with multiple queens on the same board?."&gt;&lt;/a&gt;Stalking her prey…&lt;/p&gt;

&lt;p&gt;This next algorithm was really fun and a bit more challenging. The &lt;a href="http://jeffe.cs.illinois.edu/teaching/algorithms/"&gt;Algorithms book&lt;/a&gt; I’m going through went through several more examples of breaking a problem into a smaller, simpler problem and letting recursion CPU its way to a solution, like the &lt;a href="https://rust.graystorm.com/2020/07/15/merge-sort-with-rust/"&gt;merge sort&lt;/a&gt; we just looked at. Then I moved on to chapter 2 about “backtracking” into the n Queens Problem!&lt;/p&gt;

&lt;h2&gt;
  
  
  How Many Queens?
&lt;/h2&gt;

&lt;p&gt;According to the book, the “n Queens Problem” is a prime example of using backtracking to solve a problem. Backtracking is another way to reduce a hard problem down into smaller chunks that are more easily solvable. In this case, showing the solution as it is worked out with a recursion tree model really explains well the approach used here. Go see page numbered 71 of the PDF to check it out. After just a couple of pages, Erickson moves on to the related topic of Game Trees, but this n Queens Problem seemed really fun to me.&lt;/p&gt;

&lt;p&gt;I first wanted to try and show the solutions as text-based chessboards (plus allow for the boring array version showing one solution per line). It took me a little while to setup the Rust crate &lt;a href="https://crates.io/crates/crossterm"&gt;crossterm&lt;/a&gt; to help me out with this. I had only recently heard of crossterm while watching a &lt;a href="https://www.youtube.com/watch?v=YFzF1AHYjes&amp;amp;t=7563s"&gt;YouTube video&lt;/a&gt; by David Pedersen as he codes up a simple Git helper with Rust. I didn’t go crazy with color or UTF-8 like I could have, but feel free.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let’s Rust
&lt;/h2&gt;

&lt;p&gt;Then came the matter of converting the algorithm pseudo code from the PDF into Rust code. This was slightly more difficult as Rust is very careful about array bounds checking and I had to be a little safer with my IF checks than the pseudo code warned about.&lt;/p&gt;

&lt;p&gt;Since it is Creative Commons, I can include the pseudo-code presented in Jeff Erickson’s &lt;em&gt;Algorithm&lt;/em&gt; book – but go check it out &lt;a href="http://jeffe.cs.illinois.edu/teaching/algorithms/"&gt;via his site&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--g3sweayS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i1.wp.com/rust.graystorm.com/wp-content/uploads/2020/07/queens_problem.png%3Fw%3D840%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--g3sweayS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i1.wp.com/rust.graystorm.com/wp-content/uploads/2020/07/queens_problem.png%3Fw%3D840%26ssl%3D1" alt=""&gt;&lt;/a&gt;&lt;em&gt;Figure 2.2, Page 71 from Algorithm by Jeff Erickson&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When you run the queens_problem binary, you pass along an argument of how big your chessboard square is. Optionally you can include a second param (of anything, the code doesn’t really care) which causes it to output chessboards rather than the array dumps.&lt;/p&gt;

&lt;h2&gt;
  
  
  main.rs for queens_problem
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use crossterm::{
    style::{Color, Colors, Print, ResetColor, SetColors},
    ExecutableCommand,
};
use std::env;
use std::io::stdout;

const QUEEN: &amp;amp;str = "&amp;lt;W&amp;gt;";
const EMPTY: &amp;amp;str = "   ";

/// Adapted from reading "Algorithms" by Jeff Erickson
/// freely available on http://jeffe.cs.illinois.edu/teaching/algorithms/
pub fn main() {
    let args: Vec&amp;lt;String&amp;gt; = env::args().collect();

    // nothing fancy at all, just brute-force it
    if args.len() &amp;lt; 2 || args.len() &amp;gt; 3 {
        println!("Usage: {} n [show]", args[0]);
        println!("  n = size of chessboard");
        println!("  [show] to actually see each chessboard solution");
        return;
    }

    let boardsize = args[1].parse::&amp;lt;usize&amp;gt;().unwrap();
    let chessboard = vec![-1i8; boardsize];
    let showboard = args.len() == 3; // don't even care what it is

    place_queens(chessboard.clone(), 0, showboard);
}

fn show_chessboard(board: Vec&amp;lt;i8&amp;gt;, showboard: bool) {
    let mut light: bool = true;

    if showboard {
        for pos in board.to_vec() {
            for cell in 0..board.len() {
                match (pos == cell as i8, light) {
                    (true, true) =&amp;gt; draw_square(Colors::new(Color::Black, Color::Grey), QUEEN),
                    (true, false) =&amp;gt; draw_square(Colors::new(Color::Grey, Color::Black), QUEEN),
                    (false, true) =&amp;gt; draw_square(Colors::new(Color::Black, Color::Grey), EMPTY),
                    (false, false) =&amp;gt; draw_square(Colors::new(Color::Grey, Color::Black), EMPTY),
                };
                light = !light;
            }
            println!();
            if board.len() % 2 == 0 {
                // to checkerboard even-sized boards
                light = !light;
            }
        }
        println!("\n");
    } else {
        let adjusted: Vec&amp;lt;i8&amp;gt; = board.iter().map(|&amp;amp;p| p + 1).collect(); // lets remove the 0-based confusion
        println!("{:?}", adjusted);
    }
}

fn draw_square(color: Colors, chesspiece: &amp;amp;str) {
    let mut stdout = stdout();

    stdout.execute(SetColors(color)).unwrap();
    stdout.execute(Print(chesspiece)).unwrap();
    stdout.execute(ResetColor).unwrap();
}

/// n Queens Problem
/// Section2.1, page 69-71
fn place_queens(mut chessboard: Vec&amp;lt;i8&amp;gt;, row: usize, showboard: bool) {
    if row == chessboard.len() {
        show_chessboard(chessboard.to_vec(), showboard);
        return;
    }
    for column in 0..chessboard.len() {
        let mut legal = true;
        for cell in 0..row {
            let pos = cell as usize;
            if chessboard[pos] == (column as i8)
                || (column + row &amp;gt;= cell &amp;amp;&amp;amp; chessboard[pos] == ((column + row - cell) as i8))
                || (column + cell &amp;gt;= row &amp;amp;&amp;amp; chessboard[pos] == ((column + cell - row) as i8))
            {
                legal = false;
            }
        }
        if legal {
            chessboard[row] = column as i8;
            place_queens(chessboard.clone(), row + 1, showboard);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Just a Hint of Verification
&lt;/h2&gt;

&lt;p&gt;As nerdy as they look, I used the array dumps to validate my code against what Wiki article on the &lt;a href="https://en.wikipedia.org/wiki/Eight_queens_puzzle"&gt;8 Queens Puzzle&lt;/a&gt; has as the number of valid solutions for different sized boards. I verified a 4×4 up to 14×14 board and matched the expected counts perfectly. Go check out the README for this &lt;a href="https://github.com/jculverhouse/queens_problem"&gt;repo in Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://rust.graystorm.com/2020/07/16/next-algorithm-backtracking-into-the-n-queens-problem/"&gt;Next Algorithm: Backtracking into the n Queens Problem&lt;/a&gt; appeared first on &lt;a href="https://rust.graystorm.com"&gt;Learning Rust&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>learning</category>
      <category>practice</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>Merge Sort With Rust</title>
      <dc:creator>Jeff Culverhouse</dc:creator>
      <pubDate>Thu, 16 Jul 2020 02:39:54 +0000</pubDate>
      <link>https://forem.com/jculverhouse/merge-sort-with-rust-1ood</link>
      <guid>https://forem.com/jculverhouse/merge-sort-with-rust-1ood</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--duztP75U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/rust.graystorm.com/wp-content/uploads/2020/07/play-number-community-close-up-font-toys-1091567-pxhere.com_.jpg%3Fw%3D840%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--duztP75U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/rust.graystorm.com/wp-content/uploads/2020/07/play-number-community-close-up-font-toys-1091567-pxhere.com_.jpg%3Fw%3D840%26ssl%3D1" alt="Little cubes of letters to indicate alphabetical sorting with a mergesort"&gt;&lt;/a&gt;Quick, sort; no not with quicksort, with merge sort&lt;/p&gt;

&lt;p&gt;Another algorithm to play with. Moving on in the &lt;a href="http://jeffe.cs.illinois.edu/teaching/algorithms/"&gt;Algorithms book&lt;/a&gt; I mentioned in the &lt;a href="https://rust.graystorm.com/2020/07/14/algorithmic-rust/"&gt;last post&lt;/a&gt; to section 1.4 we come across the merge sort. Another fun one to play with in Rust and to learn vectors just a little better. So let’s code up a quick merge sort with Rust!&lt;/p&gt;

&lt;h2&gt;
  
  
  Yes, I’m That Old
&lt;/h2&gt;

&lt;p&gt;My AP computer class back around the mid 1980s was in &lt;a href="https://en.wikipedia.org/wiki/Pascal_(programming_language)"&gt;Pascal&lt;/a&gt;. I later learned that Pascal was never meant to be used in production – it was a purely a teaching language – even to the extent it could be taught on paper and never even compiled. How terrible it would be not to see your first programs run!&lt;/p&gt;

&lt;p&gt;Either way, we worked on terminals and Pascal worked out just fine for me. That language led me easily to C and, though I never used C professionally, that made for an easy transition to Perl (which I have) and to Rust! It turned out, the prior few years of AP tests had been bad enough across all the high schools, they decided to omit three sections of Pascal, unless you optionally wanted to learn them and take an extra AP test, which I did. These three subjects were: recursion (the algorithms both last time and this time use recursion), linked list (that broke my brain for a little while – I was glad later on that it happened in school because it made C so much easier to learn), and sorting (without any simple, built-ins).&lt;/p&gt;

&lt;h2&gt;
  
  
  Merging with Rust
&lt;/h2&gt;

&lt;p&gt;I am sure I learned the simple merge sort back then, 35 years ago. Heck, that means it was only 40 years old when I learned it! The book only spends a couple of pages on it – it is just another example of a recursive algorithm. It was fun in Rust though, I learned some vector methods I wasn’t aware of like the various forms of split_at and concat. Again I made a couple of very simple tests just to help show it works.&lt;/p&gt;

&lt;p&gt;So, here is the code I came up with:&lt;/p&gt;

&lt;h2&gt;
  
  
  main.rs for merge sort
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use std::env;

#[test]
fn check_mergesort() {
    let letters = vec!["s", "a", "m", "p", "l", "e"];
    let shouldbe = vec!["a", "e", "l", "m", "p", "s"];
    let sorted = mergesort(letters);
    assert_eq!(sorted, shouldbe);

    let words = vec![
        "now", "is", "the", "time", "for", "all", "good", "men", "to", "come", "to", "the", "aid",
        "of", "their", "country",
    ];
    let shouldbe = vec![
        "aid", "all", "come", "country", "for", "good", "is", "men", "now", "of", "the", "the",
        "their", "time", "to", "to",
    ];
    let sorted = mergesort(words);
    assert_eq!(sorted, shouldbe);
}

/// Adapted from reading "Algorithms" by Jeff Erickson
/// freely available on http://jeffe.cs.illinois.edu/teaching/algorithms/
pub fn main() {
    let args: Vec&amp;lt;String&amp;gt; = env::args().collect();

    if args.len() &amp;lt; 2 {
        println!(
            "Usage: {} word word [word...] (two or more words to sort)",
            args[0]
        );
        return;
    }

    let words = args.iter().skip(1).map(AsRef::as_ref).collect();
    println!("Arrived: {:?}", words);

    let sorted = mergesort(words);
    println!("Sorted: {:?}", sorted);
}

/// Mergesort
/// Section 1.4, page 27
pub fn mergesort(words: Vec&amp;lt;&amp;amp;str&amp;gt;) -&amp;gt; Vec&amp;lt;&amp;amp;str&amp;gt; {
    if words.len() &amp;lt; 2 {
        return words;
    }

    let midpoint = (words.len() + 1) / 2;
    let (left, right) = words.split_at(midpoint);

    let left = mergesort(left.to_vec());
    let right = mergesort(right.to_vec());

    let halfsort = [left, right].concat();
    let sorted = merge(halfsort, midpoint);

    return sorted;
}

pub fn merge(words: Vec&amp;lt;&amp;amp;str&amp;gt;, midpoint: usize) -&amp;gt; Vec&amp;lt;&amp;amp;str&amp;gt; {
    let size = words.len();
    let mut left_index = 0;
    let mut right_index = midpoint;
    let mut sorted: Vec&amp;lt;&amp;amp;str&amp;gt; = Vec::new();

    for _ in 0..size {
        if right_index &amp;gt;= size {
            sorted.push(&amp;amp;words[left_index]);
            left_index += 1;
        } else if left_index &amp;gt;= midpoint {
            sorted.push(&amp;amp;words[right_index]);
            right_index += 1;
        } else if words[left_index] &amp;lt; words[right_index] {
            sorted.push(&amp;amp;words[left_index]);
            left_index += 1;
        } else {
            sorted.push(&amp;amp;words[right_index]);
            right_index += 1;
        }
    }
    return sorted;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There is not really much to say about it though – unless you have questions or suggestions. Check it out in the &lt;a href="https://github.com/jculverhouse/mergesort"&gt;github repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://rust.graystorm.com/2020/07/15/merge-sort-with-rust/"&gt;Merge Sort With Rust&lt;/a&gt; appeared first on &lt;a href="https://rust.graystorm.com"&gt;Learning Rust&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>learning</category>
      <category>practice</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>Algorithmic Rust</title>
      <dc:creator>Jeff Culverhouse</dc:creator>
      <pubDate>Tue, 14 Jul 2020 16:37:02 +0000</pubDate>
      <link>https://forem.com/jculverhouse/algorithmic-rust-3f35</link>
      <guid>https://forem.com/jculverhouse/algorithmic-rust-3f35</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QnDaLJLC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/rust.graystorm.com/wp-content/uploads/2020/07/keyboard-technology-number-office-gadget-electronic-1001014-pxhere.com_.jpg%3Fw%3D840%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QnDaLJLC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/rust.graystorm.com/wp-content/uploads/2020/07/keyboard-technology-number-office-gadget-electronic-1001014-pxhere.com_.jpg%3Fw%3D840%26ssl%3D1" alt="handheld calculator, algorithm driven by tiny solar panels"&gt;&lt;/a&gt;Old school – how many of these are sold these days?&lt;/p&gt;

&lt;p&gt;Well, I’m bored with my &lt;a href="https://rust.graystorm.com/2019/07/13/piecing-together-a-rust-web-application/"&gt;fake web app&lt;/a&gt;. Because I don’t know where to go next, because it doesn’t have a design or plan, because it is fake. I want to play (practice) writing Rust, but the weird “practice-this” sites always seem overly contrived: “replace all the capital letters in a given string with their ASCII-number”. Sigh. So, I’m trying something new – and probably will get over my head in no time. How about I dive into the world of algorithms: with Rust!&lt;/p&gt;

&lt;h2&gt;
  
  
  An 80’s Kid
&lt;/h2&gt;

&lt;p&gt;I never had a formal computer science education – I grew up in the sweet spot of when nerdy kids just hacked on code and tried to make things work. I barely played computer games as a teenager, but it was very common for me to be up half the night typing in some code from a &lt;a href="https://en.wikipedia.org/wiki/Compute!"&gt;COMPUTE! magazine&lt;/a&gt;. Then, once it was finally in and working, adjusting the code to tweek how it ran. Oh wow – for instance, check out the code for &lt;a href="https://archive.org/details/1983-07-compute-magazine/page/n57/mode/2up"&gt;RATS!&lt;/a&gt;. Anyway, the world is hidden with such great treasures, not all of them from the 80’s! Take, for example, a professor who, after teaching for a decade decides to revise and cleanup his lecture notes and, while doing so, turns them into a freely available book on algorithms. Sure, you can &lt;a href="https://www.amazon.com/dp/1792644833"&gt;buy his book on Amazon&lt;/a&gt; for $30, but just visit &lt;a href="http://jeffe.cs.illinois.edu/teaching/algorithms/"&gt;Jeff Erickson’s site&lt;/a&gt; to get his 448-page PDF for free!! Little did I realize, until into the first chapter, this book/course is apparently NOT for undergraduates. Oh well, I’ll see how far I can get.&lt;/p&gt;

&lt;h2&gt;
  
  
  Come At Me
&lt;/h2&gt;

&lt;p&gt;Anyway, as I’m reading through chapter 1 with the stress-free page turning of someone who won’t be actually tested on any of this. I come across a pseudo-code algorithm for something called “Peasant Multiplication”. But, I won’t murder the explanation here, just go download Erickson’s PDF. I will, however, show my interpretation of how to code that in Rust!&lt;/p&gt;

&lt;p&gt;So here is what I came up for the algorithm itself and wrapped it so the user can try, plus there is a simple test:&lt;/p&gt;

&lt;h2&gt;
  
  
  main.rs
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use std::env;

#[test]
fn check_peasant_mult() {
  use rand::Rng;
  let mut rng = rand::thread_rng();
  for _ in 0..10 {
    let n1 = rng.gen_range(1, 10000);
    let n2 = rng.gen_range(1, 10000);
    assert_eq!(peasant_multiplication(n1, n2), n1 * n2);
  }
}

/// Adapted from reading "Algorithms" by Jeff Erickson
/// freely available on http://jeffe.cs.illinois.edu/teaching/algorithms/
pub fn main() {
  let args: Vec&amp;lt;String&amp;gt; = env::args().collect();
  if args.len() != 2 {
    println!("Usage: {} x y (two positive integers)", args[0]);
    return;
  }
  let x = args[1].parse::&amp;lt;u32&amp;gt;().unwrap();
  let y = args[2].parse::&amp;lt;u32&amp;gt;().unwrap();
  let answer = peasant_multiplication(x, y);
  println!("{} x {} = {}", x, y, answer);
}

/// Peasant Multiplication
/// Section 1.2, page 23
pub fn peasant_multiplication(x: u32, y: u32) -&amp;gt; u32 {
  if x == 0 {
    return 0;
  }

  let x_prime = x / 2;
  let y_prime = y + y;
  let mut prod = peasant_multiplication(x_prime, y_prime);
  if x % 2 &amp;gt; 0 {
    prod += y;
  }
  return prod;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I thought it would be funny for someone to notice my multiplication algorithm required a random-number-generator if they looked into my Cargo.toml file, but TIL about the [dev-dependencies] section where you can list things you only need for testing! So:&lt;/p&gt;

&lt;h2&gt;
  
  
  Cargo.toml
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[package]
name = "peasant_mult"
version = "0.1.0"
authors = ["Jeff Culverhouse &amp;lt;jeff@graystorm.com&amp;gt;"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

[dev-dependencies]
rand = "0.7"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There is absolutely no reason to do multiplication this way, of course. But it let me practice my Rust WHILE learning about algorithms in computer science. It doesn’t do much, but at least it feels worthwhile and not contrived. THIS is how some people (long, long ago) did multiplication – and it was fun to reproduce it. Multiplication inside your computer’s CPU doesn’t happen the way you think either, but I don’t know anything about that so go off on a Google tangent if you like!&lt;/p&gt;

&lt;p&gt;Anyway, this one is simple and short enough I think I’ll just leave you the exercise of getting his PDF and comparing his quick mention of Peasant Multiplication and my implementation. You probably see something to improve or ways in which I am not writing idiomatic Rust (like that for loop in the test). Feel free to suggest some changes here! Also, I put &lt;a href="https://github.com/jculverhouse/peasant_mult"&gt;this up on github&lt;/a&gt;, because why not? And I have some more coming.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://rust.graystorm.com/2020/07/14/algorithmic-rust/"&gt;Algorithmic Rust&lt;/a&gt; appeared first on &lt;a href="https://rust.graystorm.com"&gt;Learning Rust&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>learning</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>Giving My App Secrets to the AWS SecretsManager</title>
      <dc:creator>Jeff Culverhouse</dc:creator>
      <pubDate>Sat, 11 Jul 2020 19:10:09 +0000</pubDate>
      <link>https://forem.com/jculverhouse/giving-my-app-secrets-to-the-aws-secretsmanager-3iho</link>
      <guid>https://forem.com/jculverhouse/giving-my-app-secrets-to-the-aws-secretsmanager-3iho</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4y7jWRyS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/rust.graystorm.com/wp-content/uploads/2020/07/person-people-girl-woman-portrait-spring-21589-pxhere.com_.jpg%3Fw%3D840%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4y7jWRyS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/rust.graystorm.com/wp-content/uploads/2020/07/person-people-girl-woman-portrait-spring-21589-pxhere.com_.jpg%3Fw%3D840%26ssl%3D1" alt="Mother telling a child a secret. Is AWS my child in this image??"&gt;&lt;/a&gt;Psst… want an API key?&lt;/p&gt;

&lt;p&gt;I’m still working around my PinPointShooting app without actually making any app progress. You can go back to the &lt;a href="https://rust.graystorm.com/2019/07/13/piecing-together-a-rust-web-application/"&gt;start&lt;/a&gt; if you like or just jump in here. So far, I’ve had my app ids and secrets hidden inside a .env file, but rather than keep them so close to the code, lets move them into my Amazon Web Services (AWS) account. It will cost me an extra $2.40/month to store these 6 secrets (so far) at Amazon ($0.40/month/secret it claims), but it gets me more practice using the rusoto_core crate and its subsidiaries. So, here is how I went about giving all of my app secrets to the AWS SecretsManager.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cargo.toml Changes
&lt;/h2&gt;

&lt;p&gt;First, in Cargo.toml, I already have rusoto_core and rusoto_dynamodb for storing my session data. So I only need to add rusoto_secretsmanager:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[dependencies]slog = "2.5.0"
slog-bunyan = "2.1.0"
base64 = "0.10.1"
rand = "0.7.0"
rand_core = "0.5.0"
rust-crypto = "0.2.36"
config = "0.9.3"
serde_json = "1.0.40"
once_cell = "0.2.2"
dotenv = "0.14.1"
rocket-slog = "0.4.0"
sha2 = "0.8.0"
rusoto_core = "0.40.0"
rusoto_dynamodb = "0.40.0"
rusoto_secretsmanager = "0.40.0"
time = "0.1.42"
google-signin = "0.3.0"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Store Those Secrets in AWS
&lt;/h2&gt;

&lt;p&gt;Of course, I had to log into AWS and create these 6 new secrets. In case I need more for other applications in the future, I prefixed each of these with “PPS_”. So, I created:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Secret name&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PPS_google_api_client_id&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PPS_google_api_client_secret&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PPS_google_maps_api_key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PPS_facebook_app_id&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PPS_facebook_app_secret&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PPS_database_url&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
List of secrets I created in my AWS account



&lt;p&gt;For each, I choose the “Other type of secrets (e.g. API key)” as the type. I stored the pair as “key” and the value I wanted to protect as a secret. This becomes the very simple struct:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#[derive(Debug, Deserialize)]
struct AWSSecret {
  key: String,
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So, instead of pulling these into my global CONFIG from the .env file, I want to pull them from AWS instead. This requires changes to the settings.rs file. First I add the requirements at the top:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use rusoto_core::Region;
use rusoto_secretsmanager::{GetSecretValueRequest, SecretsManager, SecretsManagerClient};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;plus I define the AWSSecret struct I mentioned above. Now, right after I pull in all the config settings, just before I try to turn that into a Lazy::New object to initialize the CONFIG, I need to add yet another place to pull settings from. Lets loop through each of the 6 and pull them down from AWS:&lt;/p&gt;

&lt;h2&gt;
  
  
  Pull Into Config
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// now pull secrets from AWS
// note, AWS secrets include PPS_ prefix for this application
for secret in vec![
  "database_urls",
  "google_api_client_id",
  "google_api_client_secret",
  "google_maps_api_key",
  "facebook_app_id",
  "facebook_app_secret",
] {
  config
    .set(secret, get_secret(format!("PPS_{}", secret)).key)
    .unwrap();
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So, for each Config setting stored on AWS, try to get that secret, prepending a “PPS_” in front of the secret name when checking AWS. Now I just write that get_secret() function:&lt;/p&gt;

&lt;h2&gt;
  
  
  get_secrets stored at AWS
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fn get_secret(secret: String) -&amp;gt; AWSSecret {
  let secrets_manager = SecretsManagerClient::new(Region::UsEast1);
  match secrets_manager
    .get_secret_value(GetSecretValueRequest {
      secret_id: secret.clone(),
      ..Default::default()
    })
    .sync() {
      Ok(resp) =&amp;gt; serde_json::from_str(&amp;amp;resp.secret_string.unwrap()).unwrap(),
      Err(err) =&amp;gt; panic!("Could not retrieve secret {} from AWS: {:?}", secret, err),
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I’ll probably look back on this code in 6 months or a year and cringe, but this works anyway – and dies if it fails to pull a secret, which is what I want. I guess get_secret could return Some(AWSSecret) or None… but None means something in the app will break – I might as well just panic!&lt;/p&gt;

&lt;p&gt;Of course, my AWS credentials are still stored in the .env file. Who protects the secret the protects the secrets!? Anyway, I did update the .env.sample file to reflect the new setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# configure for your user and rename to .env
ROCKET_ENV=development
AWS_ACCESS_KEY_ID=your_key_here
AWS_SECRET_ACCESS_KEY=your_key_here

# store as AWS secrets: key/value
#PPS_database_url (for example "postgres://user:password@localhost/pinpoint")
#PPS_google_api_client_id
#PPS_google_api_client_secret
#PPS_google_maps_api_key
#PPS_facebook_app_id
#PPS_facebook_app_secret
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As always, see &lt;a href="https://www.pinpointshooting.com/"&gt;PinPointShooting.com&lt;/a&gt; to see just how little it does so far (if it happens to be running), or more exciting: go see the &lt;a href="https://github.com/jculverhouse/pinpoint_shooting"&gt;git repo&lt;/a&gt;itself.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://rust.graystorm.com/2020/07/11/giving-my-app-secrets-to-the-aws-secretmanager/"&gt;Giving My App Secrets to the AWS SecretsManager&lt;/a&gt; appeared first on &lt;a href="https://rust.graystorm.com"&gt;Learning Rust&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>aws</category>
      <category>rusoto</category>
      <category>secretmanager</category>
    </item>
    <item>
      <title>Scraping off the Dust: Redeploy of my Rust web app</title>
      <dc:creator>Jeff Culverhouse</dc:creator>
      <pubDate>Thu, 02 Jul 2020 17:11:23 +0000</pubDate>
      <link>https://forem.com/jculverhouse/scraping-off-the-dust-redeploy-of-my-rust-web-app-94b</link>
      <guid>https://forem.com/jculverhouse/scraping-off-the-dust-redeploy-of-my-rust-web-app-94b</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BE1p_bgH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i1.wp.com/rust.graystorm.com/wp-content/uploads/2020/07/honey-busy-pattern-insect-invertebrate-bee-928380-pxhere.com_.jpg%3Fw%3D840%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BE1p_bgH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i1.wp.com/rust.graystorm.com/wp-content/uploads/2020/07/honey-busy-pattern-insect-invertebrate-bee-928380-pxhere.com_.jpg%3Fw%3D840%26ssl%3D1" alt="Busy as a bee"&gt;&lt;/a&gt;&lt;br&gt;
Life has been busy – no apologies or excuses, but, ya know, it’s 2020. Yet, I’m trying to slowly make my way back into playing with Rust. I decided to move my EC2 instance from AWS-Linux to the Ubuntu image; for one, I got tired of fighting with LetsEncode to get it to renew my SSL cert every 3 months. Also, I wanted to see how a redeploy of my Rust web app would go and if it still worked (why wouldn’t it?). So, lets see how tough it is to get my environment back to the same place. I took some notes (in case I needed to restart, sigh), so let’s go through it.&lt;/p&gt;

&lt;p&gt;Go back to &lt;a href="https://rust.graystorm.com/2019/07/13/piecing-together-a-rust-web-application/"&gt;Part 1&lt;/a&gt;to see what this fake web app is about and how I got here – I need to reread it myself! So, first, this is what I ended up needing to add to what I got from the default Ubuntu image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install build-essential checkinstall zlib1g-dev pig-config libssl-dev libpq-dev postgresql postgresql-contrib -y
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Lots of that was needed in order to get OpenSSL installed, I was following along hints &lt;a href="https://cloudwafer.com/blog/installing-openssl-on-ubuntu-16-04-18-04/"&gt;here&lt;/a&gt;. Continuing those instructions, I did:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd /usr/local/src/
sudo wget https://www.openssl.org/source/openssl-1.1.1g.tar.gz
sudo tar -xf openssl-1.1.1g.tar.gz
cd openssl-1.1.1g
sudo ./config --prefix=/usr/local/ssl --openssldir=/usr/local/ssl shared zlib
sudo make
sudo make test
sudo make install
sudo echo "/usr/local/ssl/lib" &amp;gt; /etc/ld.so.conf.d/openssl-1.1.1g.conf
sudo ldconfig -v
sudo mv /usr/bin/c_rehash /usr/bin/c_rehash.backup
sudo mv /usr/bin/openssl /usr/bin/openssl.backup
sudo nano /etc/environment # to add "/usr/local/ssl/bin" to the PATH
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, instead of solely storing my code on a potentially tenuous EC2 server, I wanted to keep it backed up on my Google Drive (or whatever you like, this solution works with MANY network storage). I used &lt;a href="https://rclone.org/install/"&gt;rclone&lt;/a&gt; for my Raspberry Pi photo frame so I was familiar with that already.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl https://rclone.org/install.sh | sudo bash
rclone config # to add google drive and authorize it
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Ok, the most fun step!!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl https://sh.rustup.rs -sSf | sh
cd ~/projects/rust
git clone git@github.com:jculverhouse/pinpoint_shooting.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I need nginx for my app&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install nginx
sudo service nginx start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And now the much more reliable LetsEncrypt using Ubuntu 18.04&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# follow instructions at https://certbot.eff.org/lets-encrypt
# setup root cronjob to renew once/week
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For my Rocket-powered Rust app, I followed some reminders &lt;a href="https://gist.github.com/belst/ff36c5f3883f7bf9b06c379d0a7bed9e"&gt;here&lt;/a&gt; to connect it to nginx. Simple enough, really, mostly relevant:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
server_name pinpointshooting.com; # managed by Certbot
location {
  proxy_pass http://127.0.0.1:3000;
}
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;What? Nginx still has TLS 1 and 1.1 turned on by default? Followed &lt;a href="https://libre-software.net/tls-nginx/"&gt;this&lt;/a&gt; and removed those, tested the config, and restarted nginx. All of that I checked with SSLLabs via &lt;a href="https://www.ssllabs.com/ssltest/analyze.html"&gt;https://www.ssllabs.com/ssltest/analyze.html&lt;/a&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nano /etc/nginx/nginx.conf # to remove TLS1 TLS1.1 from any line
sudo nano /etc/letsencrypt/options-ssl-nginx.conf # to remove TLS1 TLS1.1 from any line
sudo nginx -t
sudo service nginx reload
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I’ll need Postgres for my PinpointShooting app as well, found some steps to follow &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-18-04"&gt;here&lt;/a&gt;, plus I needed to setup for my own app and run the initial migrations to get it up-to-date. That involved &lt;a href="https://gist.github.com/AtulKsol/4470d377b448e56468baef85af7fd614"&gt;another change&lt;/a&gt; so I could login with the password from a non-user-account.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cargo install diesel_cli --no-default-features --features posters
psql -d postgres -U postgres
  create user pinpoint password 'yeahrightgetyourown'; # save this in file .env in app dir
  create database pinpoint;
  grant all privileges on database pinpoint to pinpoint;
sudo nano /etc/postgresql/10/main/pg\_hba.conf # to edit "local all all" line to be md5 instead of peer
sudo service postgresql restart
psql -d postgres -U pinpoint # to test password above; just exit
cd ~/projects/rust/pinpointshooting
diesel migration run
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Finally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rustup default nightly # because Rocket, sigh...
cargo update
cargo build --release
target/release/pps &amp;amp;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And, we’re back online! Turns out, a redeploy of my Rust web app was about as easy as I could expect! If the app happens to be running, check it out here (though, there isn’t much to see or anything to do): &lt;a href="https://pinpointshooting.com/"&gt;pinpointshooting.com&lt;/a&gt;. Also, &lt;a href="https://github.com/jculverhouse/pinpoint_shooting"&gt;browse the repo&lt;/a&gt; and feel free to send me comments on how to be better about using idiomatic Rust!&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://rust.graystorm.com/2020/07/02/scraping-off-the-dust-redeploy-of-my-rust-web-app/"&gt;Scraping off the Dust: Redeploy of my Rust web app&lt;/a&gt; appeared first on &lt;a href="https://rust.graystorm.com"&gt;Learning Rust&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>aws</category>
      <category>learning</category>
      <category>webapp</category>
    </item>
    <item>
      <title>OAuth Requests, APIs, Diesel, and Sessions</title>
      <dc:creator>Jeff Culverhouse</dc:creator>
      <pubDate>Fri, 09 Aug 2019 13:26:43 +0000</pubDate>
      <link>https://forem.com/jculverhouse/oauth-requests-apis-diesel-and-sessions-5lb</link>
      <guid>https://forem.com/jculverhouse/oauth-requests-apis-diesel-and-sessions-5lb</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi1.wp.com%2Frust.graystorm.com%2Fwp-content%2Fuploads%2F2019%2F08%2Fwheel-spiral-purple-line-pasture-metal-969319-pxhere.com_.jpg%3Fresize%3D400%252C400%26ssl%3D1" 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%2Fi1.wp.com%2Frust.graystorm.com%2Fwp-content%2Fuploads%2F2019%2F08%2Fwheel-spiral-purple-line-pasture-metal-969319-pxhere.com_.jpg%3Fresize%3D400%252C400%26ssl%3D1" alt="Intertwined woven basket material.. much like Oauth, accounts, APIs, diesel, and sessions are in this project (probably any project)"&gt;&lt;/a&gt;Things are starting to intertwine… &lt;/p&gt;

&lt;p&gt;Some big changes in the &lt;a href="https://github.com/jculverhouse/pinpoint_shooting" rel="noopener noreferrer"&gt;repository&lt;/a&gt; just recently. I added &lt;code&gt;Google Signin&lt;/code&gt; and &lt;code&gt;Facebook Signin&lt;/code&gt; &lt;a href="https://en.wikipedia.org/wiki/OAuth" rel="noopener noreferrer"&gt;OAuth&lt;/a&gt; connections. I’m thinking I may not even configure an internal password on the site for users and instead just require one of those options. Probably I’ll add more, like &lt;a href="https://500px.com/" rel="noopener noreferrer"&gt;500px.com&lt;/a&gt; and/or &lt;a href="https://www.flickr.com/" rel="noopener noreferrer"&gt;Flickr&lt;/a&gt;, given the site’s purpose. A &lt;code&gt;password&lt;/code&gt; field is still in my database though, so I haven’t given up the idea completely. Also, the OAuth requests create accounts using Diesel.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Users&lt;/code&gt; (now identified as &lt;code&gt;shooters&lt;/code&gt; – we photographers haven’t given up that term) – are now written to the db. I really fought with one Diesel feature, so that bit is still commented out in the code. In addition, I added my first API to &lt;code&gt;POST&lt;/code&gt; to – so another step with the &lt;code&gt;Rocket&lt;/code&gt;crate as well! I’d like to work my way into playing with a &lt;a href="https://graphql.org/" rel="noopener noreferrer"&gt;GraphQL&lt;/a&gt; endpoint so I can play with that as well!! (What’s the limit on Crate dependencies in a project anyway?!) I’m starting to think I won’t be able to tackle all of this in a single post – but let start!&lt;/p&gt;

&lt;h2&gt;
  
  
  OAuth vs Old and New Accounts
&lt;/h2&gt;

&lt;p&gt;When a user arrives on the site, I check for a &lt;code&gt;cookie&lt;/code&gt; with a &lt;code&gt;session id&lt;/code&gt; (see my &lt;a href="https://rust.graystorm.com/2019/08/04/rust-web-app-session-management-with-aws/" rel="noopener noreferrer"&gt;previous post&lt;/a&gt;). I decided, for now, I would use the &lt;code&gt;User Agent&lt;/code&gt; (plus some random characters) as a fingerprint for creating the session id. So, when I am able to get a &lt;code&gt;session_id&lt;/code&gt; from a cookie, I want to verify the &lt;code&gt;User Agent&lt;/code&gt; is the same and that the session hasn’t expired. If the user arrives brand new, without a cookie, I immediately create an empty, no-user session for them. All of this is done, for now, right at the top of my &lt;code&gt;index() route&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;src/routes.rs&amp;gt;

...
#[get("/")]
pub fn index(mut cookies: Cookies, nginx: Nginx) -&amp;gt; 
    rocket_contrib::templates::Template
{
    let session = get_or_setup_session(&amp;amp;mut cookies, &amp;amp;nginx);
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the &lt;code&gt;index&lt;/code&gt; page loads, it shows the Google and Facebook Sign In buttons. Clicking one of those, they do the validation dance and get permission from the user. When that is granted, my app gets a token back which I send up to the server via a &lt;code&gt;POST&lt;/code&gt; to &lt;code&gt;/api/v1/tokensignin&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;src/api.rs&amp;gt;

use rocket::{http::Cookies, post, request::Form, FromForm};
use crate::oauth::*;
use crate::routes::Nginx;
use crate::session::*;
#[derive(FromForm)]
pub struct OAuthReq {
    pub g_token: Option&amp;lt;String&amp;gt;,  // google login req
    pub fb_token: Option&amp;lt;String&amp;gt;, // facebook login req`
    pub name: String,
    pub email: String,
}
#[post("/api/v1/tokensignin", data = "&amp;lt;oauth_req&amp;gt;")]
pub fn tokensignin(mut cookies: Cookies, nginx: Nginx,
        oauth_req: Form&amp;lt;OAuthReq&amp;gt;) -&amp;gt; String
{
    let mut session = get_or_setup_session(&amp;amp;mut cookies, &amp;amp;nginx);
    if let Some(token) = &amp;amp;oauth_req.g_token {
        match verify_google_oauth(&amp;amp;mut session, &amp;amp;token,
            &amp;amp;oauth_req.name, &amp;amp;oauth_req.email)
        {
            true =&amp;gt; {
                session.google_oauth = true;
                save_session_to_ddb(&amp;amp;mut session);
                "success".to_string()
            }
            false =&amp;gt; {
                session.google_oauth = false;
                save_session_to_ddb(&amp;amp;mut session);
                "failed".to_string()
            }
        }
    } else if let Some(token) = &amp;amp;oauth_req.fb_token {
        match verify_facebook_oauth(&amp;amp;mut session, &amp;amp;token,
            &amp;amp;oauth_req.name, &amp;amp;oauth_req.email)
        {
            true =&amp;gt; {
                session.facebook_oauth = true;
                save_session_to_ddb(&amp;amp;mut session);
                "success".to_string()
            }
            false =&amp;gt; {
                session.facebook_oauth = false;
                save_session_to_ddb(&amp;amp;mut session);
                "failed".to_string()
            }
        }
    } else {
        "no token sent".to_string()
    }
}

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  OAuth Requests via HTTP POSTs
&lt;/h2&gt;

&lt;p&gt;This is how you allow for a &lt;code&gt;POST&lt;/code&gt; and &lt;code&gt;form data&lt;/code&gt; to come in – you setup a &lt;code&gt;struct&lt;/code&gt; (&lt;code&gt;OAuthReq&lt;/code&gt; in my example) of what you expect and bring that in as an input param. Plus, I am also bringing in any &lt;code&gt;cookies&lt;/code&gt; that arrive with the request plus some Nginx headers so I have access to &lt;code&gt;UserAgent&lt;/code&gt;. In the code so far, I’m either verifying a Google or Facebook token. Let’s look at the Google example (the Facebook one is nearly the same). Here are the relevant parts, but I’ll break some pieces down and go through it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;src/oauth.rs&amp;gt;

...
pub fn verify_google_oauth(
    session: &amp;amp;mut Session,
    token: &amp;amp;String,
    name: &amp;amp;String,
    email: &amp;amp;String,
) -&amp;gt; bool {
    let mut google = google_signin::Client::new();
    google.audiences.push(CONFIG.google_api_client_id.clone());
    let id_info = google.verify(&amp;amp;token).expect("Expected token to be valid");
    let token = id_info.sub.clone();
    verify_token(session, "google".to_string(), &amp;amp;token, &amp;amp;name, &amp;amp;email)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which leads right away to a big &lt;code&gt;match&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fn verify_token(
    session: &amp;amp;mut Session,
    vendor: String,
    token: &amp;amp;String,
    name: &amp;amp;String,
    email: &amp;amp;String,
) -&amp;gt; bool {
    use crate::schema::oauth::dsl::*;
    use crate::schema::shooter::dsl::*;
    let connection = connect_pgsql();
    match oauth
        .filter(oauth_vendor.eq(&amp;amp;vendor))
        .filter(oauth_user.eq(&amp;amp;token))
        .first::&amp;lt;Oauth&amp;gt;(&amp;amp;connection)
    {
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the OK arm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        // token WAS found in oauth table
        Ok(o) =&amp;gt; {
            if let Some(id) = session.shooter_id {
                if id == o.shooter_id {
                    return true;
                } else {
                    return false;
                }
            } else {
                // log in user - what IS the problem with BelongsTo!?
                //if let Ok(s) = Shooter::belonging_to(&amp;amp;o)
                //    .load::&amp;lt;Shooter&amp;gt;(&amp;amp;connection)
                //{
                //    session.shooter_id = Some(shooter.shooter_id);
                //    session.shooter_name = Some(shooter.shooter_name);
                //    session.email_address = Some(shooter.email);
                return true;
                //} else {
                //    return false;
                //}
            }
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the ERR arms:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        // token not found in oauth table
        Err(diesel::NotFound) =&amp;gt; match session.shooter_id {
            Some(id) =&amp;gt; {
                create_oauth(&amp;amp;connection, &amp;amp;vendor, token, id);
                true
            }
            None =&amp;gt; match shooter
                .filter(shooter_email.eq(&amp;amp;email))
                .first::&amp;lt;Shooter&amp;gt;(&amp;amp;connection)
            {
                // email address WAS found in shooter table
                Ok(s) =&amp;gt; {
                    create_oauth(&amp;amp;connection, &amp;amp;vendor, token, s.shooter_id);
                    true
                }
                // email address not found in shooter table
                Err(diesel::NotFound) =&amp;gt; {
                    let this_shooter =
                        create_shooter(&amp;amp;connection, name, None,
                            email, &amp;amp;"active".to_string());
                    session.shooter_id = Some(this_shooter.shooter_id);
                    create_oauth(&amp;amp;connection, &amp;amp;vendor, token,
                        this_shooter.shooter_id);
                    true
                }
                Err(e) =&amp;gt; {
                    panic!("Database error {}", e);
                }
            },
        },
        Err(e) =&amp;gt; {
            panic!("Database error {}", e);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Simple Queries with Diesel
&lt;/h2&gt;

&lt;p&gt;Breaking all that code down to smaller bits: first, I query the PgSQL database for the given &lt;code&gt;oauth user&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;match oauth
    .filter(oauth_vendor.eq(&amp;amp;vendor))
    .filter(oauth_user.eq(&amp;amp;token))
    .first::&amp;lt;Oauth&amp;gt;(&amp;amp;connection) {
        Ok(o) =&amp;gt; { ... }
        Err(diesel::NotFound) =&amp;gt; { ... }
        Err(e) =&amp;gt; { ... }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the &lt;code&gt;oauth&lt;/code&gt; table for records WHERE (&lt;code&gt;filter&lt;/code&gt;) the &lt;code&gt;oauth_vendor&lt;/code&gt; is (google or facebook) AND I’ve already stored the same validated &lt;code&gt;oauth_user&lt;/code&gt;. I will get back either &lt;code&gt;Ok(o)&lt;/code&gt; or &lt;code&gt;Err(diesel::NotFound)&lt;/code&gt; … (or some worse error message), so I make a pattern with those 3 arms.&lt;/p&gt;

&lt;p&gt;If we did get a hit from the DB, that &lt;code&gt;session id&lt;/code&gt; is already tied to a &lt;code&gt;shooter_id&lt;/code&gt; (user id) unless something is very wrong. So, IF we also have a &lt;code&gt;shooter_id&lt;/code&gt; defined in our current &lt;code&gt;session&lt;/code&gt;, I just need to verify that they match and return true or false. But, if we don’t have a &lt;code&gt;shooter_id&lt;/code&gt; in our &lt;code&gt;session&lt;/code&gt;, we know the &lt;code&gt;oauth&lt;/code&gt; is tied to a &lt;code&gt;shooter&lt;/code&gt; in the db, so this will log them in. &lt;code&gt;Diesel&lt;/code&gt; has an easy way to get that parent record, which is what this should do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// if let Ok(s) = Shooter::belonging\_to(&amp;amp;o).load::\&amp;lt;Shooter\&amp;gt;(&amp;amp;connection) {
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I fought and fought to get this work, but you can see it is still commented out. From posts and chat around the Internet, I believe it can work – I think I either have a &lt;code&gt;scope&lt;/code&gt; problem or my &lt;code&gt;models&lt;/code&gt; aren’t setup correctly… this is how they look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;src/model.rs&amp;gt;

...
#[derive(Identifiable, Queryable, Debug, PartialEq)]
#[table_name = "shooter"]
#[primary_key("shooter_id")]
pub struct Shooter {
    pub shooter_id: i32,
    pub shooter_name: String,
    pub shooter_password: String,
    pub shooter_status: String,
    pub shooter_email: String,
    pub shooter_real_name: String,
    pub shooter_create_time: chrono::NaiveDateTime,
    pub shooter_active_time: Option&amp;lt;chrono::NaiveDateTime&amp;gt;,
    pub shooter_inactive_time: Option&amp;lt;chrono::NaiveDateTime&amp;gt;,
    pub shooter_remove_time: Option&amp;lt;chrono::NaiveDateTime&amp;gt;,
    pub shooter_modify_time: chrono::NaiveDateTime,
}
...
#[derive(Identifiable, Associations, Queryable, Debug, PartialEq)]
#[belongs_to(Shooter, foreign_key = "shooter_id")]
#[table_name = "oauth"]
#[primary_key("oauth_id")]
pub struct Oauth {
    pub oauth_id: i32,
    pub oauth_vendor: String,
    pub oauth_user: String,
    pub shooter_id: i32,
    pub oauth_status: String,
    pub oauth_create_time: chrono::NaiveDateTime,
    pub oauth_last_use_time: chrono::NaiveDateTime,
    pub oauth_modify_time: chrono::NaiveDateTime,
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I’ll get it to work eventually – I really hope it isn’t failing because I didn’t specifically name my primary fields just &lt;code&gt;id&lt;/code&gt; like in the examples &lt;code&gt;Diesel&lt;/code&gt; gives in their guides. It seems like naming &lt;code&gt;shooter_id&lt;/code&gt; in table &lt;code&gt;oauth&lt;/code&gt; to match &lt;code&gt;shooter_id&lt;/code&gt; in the &lt;code&gt;shooter&lt;/code&gt; table should make things obvious. Hopefully we aren’t forced to always use &lt;code&gt;id&lt;/code&gt; as the primary field… no, that can’t be it.&lt;/p&gt;

&lt;p&gt;Anyway, back to verifying. The other main case is that an &lt;code&gt;oauth&lt;/code&gt; record with this token is NOT found in the table. Which means it is a new connection we haven’t seen before. If the &lt;code&gt;session&lt;/code&gt; is already logged in, we just need to attach this &lt;code&gt;oauth&lt;/code&gt; token to the logged in user and return true!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Some(id) =&amp;gt; {
    create_oauth(&amp;amp;connection, &amp;amp;vendor, token, id);
    true
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Otherwise, two choices – we will try to match on an existing &lt;code&gt;shooter&lt;/code&gt; via the &lt;code&gt;email address&lt;/code&gt;. If we find a match, we log them in and again attach this oauth token to their &lt;code&gt;shooter&lt;/code&gt; record.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; None =&amp;gt; match shooter
     .filter(shooter_email.eq(&amp;amp;email))
     .first::&amp;lt;Shooter&amp;gt;(&amp;amp;connection)
 {
     // email address WAS found in shooter table
     Ok(s) =&amp;gt; {
         create_oauth(&amp;amp;connection, &amp;amp;vendor, token, s.shooter_id);
         true
     }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Otherwise, we don’t get a hit; that is, we haven’t seen this &lt;code&gt;oauth&lt;/code&gt; token before AND we haven’t seen this validated &lt;code&gt;email address&lt;/code&gt; before. We have to call that a brand new &lt;code&gt;shooter&lt;/code&gt; account. I mentioned we create accounts from the OAuth requests using Diesel – this is where that happens. In this case, we create both the &lt;code&gt;shooter&lt;/code&gt; record and the &lt;code&gt;oauth&lt;/code&gt; record, linking them together.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// email address not found in shooter table
Err(diesel::NotFound) =&amp;gt; {
    let this_shooter =
        create_shooter(&amp;amp;connection, name, None, email,
            &amp;amp;"active".to_string());
    session.shooter_id = Some(this_shooter.shooter_id);
    create_oauth(&amp;amp;connection, &amp;amp;vendor, token, this_shooter.shooter_id);
    true
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using Diesel to Insert Records
&lt;/h2&gt;

&lt;p&gt;As we fall back out of the stack of functions we’ve called, because we return &lt;code&gt;true&lt;/code&gt; here the &lt;code&gt;session&lt;/code&gt; will get updated with the &lt;code&gt;shooter_id&lt;/code&gt; – they are now logged in. Also, the &lt;code&gt;shooter&lt;/code&gt; and &lt;code&gt;oauth&lt;/code&gt; records are saved, so if they come back, they can just validate and be logged into their same account again. Here are the two methods that create those records:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;src/shooter.rs&amp;gt;

...
pub fn create_shooter&amp;lt;'a&amp;gt;(
    connection: &amp;amp;PgConnection,
    name: &amp;amp;'a String,
    password: Option&amp;lt;&amp;amp;'a String&amp;gt;,
    email: &amp;amp;'a String,
    status: &amp;amp;'a String,
) -&amp;gt; Shooter {
    use crate::schema::shooter::dsl::*;
    let new_shooter = NewShooter {
        shooter_name: name.to_string(),
        shooter_password: match password {
            Some(p) =&amp;gt; p.to_string(),
            None =&amp;gt; thread_rng()
                .sample_iter(&amp;amp;Alphanumeric)
                .take(64)
                .collect::&amp;lt;String&amp;gt;(),
        },
        shooter_status: status.to_string(),
        shooter_email: email.to_string(),
        shooter_real_name: name.to_string(),
    };
    diesel::insert_into(shooter)
        .values(&amp;amp;new_shooter)
        .get_result(connection)
        .expect("Error saving new Shooter")
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;src/oauth.rs&amp;gt;

...
pub fn create_oauth&amp;lt;'a&amp;gt;(
    connection: &amp;amp;PgConnection,
    vendor: &amp;amp;'a String,
    user_id: &amp;amp;'a String,
    shooterid: i32,
) -&amp;gt; Oauth {
    use crate::schema::oauth::dsl::*;
    let new_oauth = NewOauth {
        oauth_vendor: vendor.to_string(),
        oauth_user: user_id.to_string(),
        shooter_id: shooterid,
    };
    diesel::insert_into(oauth)
        .values(&amp;amp;new_oauth)
        .get_result(connection)
        .expect("Error saving new Oauth")
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As far as writing these new records to PgSQL – in both cases, we have &lt;code&gt;NewShooter&lt;/code&gt; and &lt;code&gt;NewOauth structs&lt;/code&gt; that allow us to set the bare minimum of fields without having to worry about the fields that PgSQL will default for us (like the &lt;code&gt;create_date&lt;/code&gt; fields). We setup the appropriate &lt;code&gt;struct&lt;/code&gt; and pass it to &lt;code&gt;insert_into()&lt;/code&gt;. Adding &lt;code&gt;.get_result()&lt;/code&gt; will return the newly created record to us, so we have access to the brand new &lt;code&gt;shooter_id&lt;/code&gt; or &lt;code&gt;oauth_id&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Complexity
&lt;/h2&gt;

&lt;p&gt;If a user comes to the site, signs in with one OAuth (which creates their shooter record and attaches that oauth token) and then signs in with the other, this logic figures out they are validated to be the same person, so creates just a single shooter record with two oauth records, and both point to the one user. If they come back, they can authenticate via either third-party and are allowed back in.&lt;/p&gt;

&lt;p&gt;Ok, more to come as I figure out other problems. I haven’t gone through that logic tightly enough to make sure I don’t have any holes – and it wouldn’t surprise me to find some. It doesn’t really matter – this is certainly teaching me Rust! Give it a try at &lt;a href="https://pinpointshooting.com/" rel="noopener noreferrer"&gt;PinpointShooting.com&lt;/a&gt; – but don’t be surprised if you &lt;code&gt;shooter&lt;/code&gt; account gets deleted, constantly.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://rust.graystorm.com/2019/08/09/oauth-requests-apis-diesel-and-sessions/" rel="noopener noreferrer"&gt;OAuth Requests, APIs, Diesel, and Sessions&lt;/a&gt; appeared first on &lt;a href="https://rust.graystorm.com" rel="noopener noreferrer"&gt;Learning Rust&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>beginners</category>
      <category>webapp</category>
      <category>oauth</category>
    </item>
    <item>
      <title>Rust Web App Session Management with AWS</title>
      <dc:creator>Jeff Culverhouse</dc:creator>
      <pubDate>Sun, 04 Aug 2019 17:35:17 +0000</pubDate>
      <link>https://forem.com/jculverhouse/rust-web-app-session-management-with-aws-webapp-5-26a0</link>
      <guid>https://forem.com/jculverhouse/rust-web-app-session-management-with-aws-webapp-5-26a0</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YMXdkrum--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i1.wp.com/rust.graystorm.com/wp-content/uploads/2019/08/writing-number-sign-key-door-security-1095191-pxhere.com_.jpg%3Fresize%3D840%252C560%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YMXdkrum--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i1.wp.com/rust.graystorm.com/wp-content/uploads/2019/08/writing-number-sign-key-door-security-1095191-pxhere.com_.jpg%3Fresize%3D840%252C560%26ssl%3D1" alt="Printed security pass - an old school session management practice&amp;lt;br&amp;gt;
"&gt;&lt;/a&gt;Didn’t someone mention a cookie too!? Where’s my cookie!?&lt;/p&gt;

&lt;p&gt;I’ve worked on some more bits with my pretend web application I introduced a &lt;a href="https://rust.graystorm.com/2019/07/13/piecing-together-a-rust-web-application/"&gt;few posts ago&lt;/a&gt;. Thinking about the technology needed to let users register and later log in, &lt;a href="https://en.wikipedia.org/wiki/Session_(computer_science)"&gt;session management&lt;/a&gt; seems like a good first step to take. I would like to store the sessions in Amazon’s &lt;a href="https://aws.amazon.com/dynamodb/"&gt;DynamoDB&lt;/a&gt; too, just for fun and experience. I’ve pushed several commits to the &lt;a href="https://github.com/jculverhouse/pinpoint_shooting"&gt;repository&lt;/a&gt; lately, so let me go through some of the changes enabling Rust web app session management with AWS DynamoDB.&lt;/p&gt;

&lt;p&gt;First, I searched and read up a bit on best practices for session management. I found a &lt;a href="https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html"&gt;Session Management Cheat Sheet&lt;/a&gt; from &lt;a href="https://www.owasp.org/index.php/Main_Page"&gt;OWASP&lt;/a&gt;. Also, more generically, &lt;a href="https://cloud.google.com/blog/products/gcp/12-best-practices-for-user-account"&gt;12 Best Practices for User Account, Authorization, and Password Management&lt;/a&gt; on the &lt;a href="https://cloud.google.com/blog/"&gt;Google Cloud Blog&lt;/a&gt;. I haven’t addressed many of these yet, but I’ll come back to resources like this several times in the future. I was trying to find language-independent whitepapers or guides on web app session management… and something not a decade old. If anyone has a definitive resource for this, please share!&lt;/p&gt;
&lt;h2&gt;
  
  
  Rusoto to the Rescue
&lt;/h2&gt;

&lt;p&gt;First, let’s get our web application interfacing with AWS. &lt;a href="https://www.rusoto.org/"&gt;Rusoto&lt;/a&gt; is a big set of &lt;a href="https://crates.io/"&gt;crates&lt;/a&gt; for using AWS services. Rusoto &lt;a href="https://crates.io/crates/rusoto_core"&gt;Core&lt;/a&gt; (of course) and &lt;a href="https://crates.io/crates/rusoto_dynamodb"&gt;DynamoDB&lt;/a&gt; are all I need for now, but I am sure I’ll come back for more! To get set up, I created a &lt;code&gt;sessions&lt;/code&gt; table in my &lt;a href="https://aws.amazon.com/"&gt;AWS&lt;/a&gt; console and created a programmatic &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html"&gt;IAM role&lt;/a&gt; called &lt;code&gt;pinpointshooting&lt;/code&gt; which has full access to the table. When creating a programmatic role, you are given &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html"&gt;credential access keys&lt;/a&gt; which I put into my &lt;code&gt;.env&lt;/code&gt; file at the root of the &lt;code&gt;pinpointshooting&lt;/code&gt; project. First, connecting to my AWS account with those access keys is a simple matter of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DynamoDbClient::new(Region::UsEast1)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vPTFXq98--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i2.wp.com/rust.graystorm.com/wp-content/uploads/2019/08/session-cookie-life.jpg%3Ffit%3D720%252C1024%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vPTFXq98--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i2.wp.com/rust.graystorm.com/wp-content/uploads/2019/08/session-cookie-life.jpg%3Ffit%3D720%252C1024%26ssl%3D1" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I had to think about the process I would use to store the &lt;code&gt;session id&lt;/code&gt; in a cookie, and when/how it gets created, verified, updated, and deleted. I came up with a simple sketch to make it more clear in my mind. Note that I mention a &lt;code&gt;cache&lt;/code&gt; both in my sketch and in some of the comments, but I haven’t done anything about that yet.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When a user arrives with &lt;strong&gt;no&lt;/strong&gt; cookie – we need to create a session with some appropriate defaults, write it to the db, and send the cookie in the resulting response.&lt;/li&gt;
&lt;li&gt;If the user arrives &lt;strong&gt;with&lt;/strong&gt; a cookie – we need to pull the session from the DB (if it really exists) and do some verification and expiration checking. If everything looks good, we pull the session details into our &lt;code&gt;struct&lt;/code&gt;. Otherwise, we delete that invalid session data and create a new session like above.&lt;/li&gt;
&lt;li&gt;When the user selects to log out – we again check to make sure the session is valid, but then delete the session, delete the cookie, and log the user out.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are those steps above, as I have them in code at this point!&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Search for or Create the Session
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Check for sessid cookie and verify session or create new
// session to use - either way, return the session struct

pub fn get_or_setup_session(cookies: &amp;amp;mut Cookies) -&amp;gt; Session {
    let applogger = &amp;amp;LOGGING.logger;
    let dynamodb = connect_dynamodb();

    // if we can pull sessid from a cookie and validate it,
    // pull session from cache or from storage and return
    if let Some(cookie) = cookies.get_private("sessid") {
        debug!(applogger, "Cookie found, verifying"; "sessid" =&amp;gt; cookie.value());
        // verify from dynamodb, update session with last-access if good
        if let Some(mut session) = 
        verify_session_in_ddb(&amp;amp;dynamodb, &amp;amp;cookie.value().to_string()) {
            save_session_to_ddb(&amp;amp;dynamodb, &amp;amp;mut session);
            return session;
        }
     }
     // otherwise, start a new, empty session to use for this user
    let mut hasher = Sha256::new();
    let randstr: String = thread_rng()
        .sample_iter(&amp;amp;Alphanumeric)
        .take(256)
        .collect();
    hasher.input(randstr);
    let sessid = format!("{:x}", hasher.result());
    cookies.add_private(Cookie::new("sessid", sessid.clone()));
    let mut session = Session {
        sessid: sessid.clone(),
        ..Default::default(),
    };
    save_session_to_ddb(&amp;amp;dynamodb, &amp;amp;mut session);
    session
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will check the (private) cookie &lt;code&gt;sessid&lt;/code&gt;, if it came along with the http request, and try to fetch it from DynamoDB and then verify it (see below). If that succeeds, we update the session (with an updated &lt;code&gt;last-access&lt;/code&gt; timestamp) and return the &lt;code&gt;session struct&lt;/code&gt;. Otherwise, we create a new &lt;code&gt;session id&lt;/code&gt;, with some appropriate defaults for now, by getting a hash of a random string of characters. Hrm, I should make sure I didn’t just happen to intersect with an existing &lt;code&gt;sessid&lt;/code&gt; at this point! Anyway, we then just add (or update) the &lt;code&gt;sessid&lt;/code&gt; cookie to be returned with the http response. Since we are using the &lt;a href="https://api.rocket.rs/v0.4/rocket/http/enum.Cookies.html#private-cookies"&gt;private cookie&lt;/a&gt; feature of &lt;a href="https://rocket.rs/"&gt;Rocket&lt;/a&gt;, the value is actually encrypted. The user can’t see what their real &lt;code&gt;session id&lt;/code&gt; is or try to manufacture one. Lastly, if we just created a new session, we save it to the session table and return it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Verify a Session
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Search for sessid in dynamodb and verify session if found
// including to see if it has expired
fn verify_session_in_ddb(dynamodb: &amp;amp;DynamoDbClient, sessid: &amp;amp;String) -&amp;gt; Option&amp;lt;Session&amp;gt; {
    let applogger = &amp;amp;LOGGING.logger;
    let av = AttributeValue {
        s: Some(sessid.clone()),
        ..Default::default(),
    };
    let mut key = HashMap::new();
    key.insert("sessid".to_string(), av);
    let get_item_input = GetItemInput {
        table_name: "session".to_string(),
        key: key,
        ..Default::default()
    };
    match dynamodb.get_item(get_item_input).sync() {
        Ok(item_output) =&amp;gt; match item_output.item {
            Some(item) =&amp;gt; match item.get("session") {
                Some(session) =&amp;gt; match &amp;amp;session.s {
                    Some(string) =&amp;gt; {
                        let session: Session = serde_json::from_str(&amp;amp;string)
                            .unwrap();
                        match session.last_access {
                            Some(last) =&amp;gt; {
                                if last &amp;gt; Utc::now() - 
                                Duration::minutes(CONFIG.sessions.expire) {
                                    Some(session)
                                } else {
                                    debug!(applogger, "Session expired";
                                        "sessid" =\&amp;gt; sessid); 
                                    delete_session_in_ddb(dynamodb, sessid);
                                    None
                                }
                            }
                            None =&amp;gt; {
                                debug!(applogger, "'last_access' is blank for stored session"; "sessid" =&amp;gt; sessid);
                                delete_session_in_ddb(dynamodb, sessid);
                                None
                            }
                        }
                    }
                    None =&amp;gt; {
                        debug!(applogger, "'session' attribute is empty for stored session"; "sessid" =&amp;gt; sessid);
                        delete_session_in_ddb(dynamodb, sessid);
                        None
                    }
                },
                None =&amp;gt; {
                    debug!(applogger, "No 'session' attribute found for stored session"; "sessid" =&amp;gt; sessid);
                    delete_session_in_ddb(dynamodb, sessid);
                    None
                }
            },
            None =&amp;gt; {
                debug!(applogger, "Session not found in dynamodb"; "sessid" =&amp;gt; sessid);
                None
            }
        },
        Err(e) =&amp;gt; {
            crit!(applogger, "Error in dynamodb"; "err" =&amp;gt; e.to_string());
            panic!("Error in dynamodb: {}", e.to\_string());
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That’s some deep nesting – I’m still a newbie at &lt;code&gt;Rust&lt;/code&gt; coding, so there is probably a better way to write this. If I didn’t care about logging the problems, I could probably shorten this by using the “?” operator at the end of each step. Maybe I’ll change that eventually, but for now I need to debugging logs to see that things are working.&lt;/p&gt;

&lt;p&gt;This chain tries to retrieve the &lt;code&gt;session&lt;/code&gt; attribute associated with the &lt;code&gt;sessid&lt;/code&gt; (session id encoded in the cookie) and for now, just makes sure it isn’t too old. If that simple check is ok, we deserialize and return that &lt;code&gt;Some(session struct)&lt;/code&gt;. In all other cases, we return &lt;code&gt;None&lt;/code&gt; and a new session will be generated. For cases where a session was present, but determined to be invalid or expired, we also delete the session from DynamoDB.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Save (or Update) the Session
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Write current session to dynamodb, update last-access date/time too
fn save_session_to_ddb(dynamodb: &amp;amp;DynamoDbClient, session: &amp;amp;mut Session) {
    let applogger = &amp;amp;LOGGING.logger;
    session.last_access = Some(Utc::now());
    let sessid_av = AttributeValue {
        s: Some(session.sessid.clone()),
        ..Default::default()
    };
    let session_av = AttributeValue {
        s: Some(serde_json::to_string(&amp;amp;session).unwrap()),
        ..Default::default()
    };
    let mut item = HashMap::new();
    item.insert("sessid".to_string(), sessid_av);
    item.insert("session".to_string(), session_av);
    let put_item_input = PutItemInput {
        table_name: "session".to_string(),
        item: item,
        ..Default::default()
     };
     match dynamodb.put_item(put_item_input).sync() {
         Ok(_) =&amp;gt; {}
         Err(e) =&amp;gt; {
             crit!(applogger, "Error in dynamodb"; "err" =&amp;gt; e.to_string());
             panic!("Error in dynamodb: {}", e.to_string());
         }
     };
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here, we simply take the session data we are passed, update the &lt;code&gt;last_access&lt;/code&gt; to &lt;code&gt;now()&lt;/code&gt; and then write the &lt;code&gt;serialized session struct&lt;/code&gt; to DynamoDB. Also note, I’m storing the session id inside the session data itself. I’m not sure yet if this is handy duplication, a security concern, or irrelevant.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Clean-up After Ourselves
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--a78E_N7c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i1.wp.com/rust.graystorm.com/wp-content/uploads/2019/08/work-man-person-repair-profession-dad-713854-pxhere.com_.jpg%3Fresize%3D512%252C342%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--a78E_N7c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i1.wp.com/rust.graystorm.com/wp-content/uploads/2019/08/work-man-person-repair-profession-dad-713854-pxhere.com_.jpg%3Fresize%3D512%252C342%26ssl%3D1" alt="Repairman cleaning up his work, but did anyone check his security badge!?"&gt;&lt;/a&gt;Hey! Are you a security concern??&lt;/p&gt;

&lt;p&gt;Just for completeness, here is the function to drop a session from DynamoDB once we have determined it is invalid (expired).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Delete session from dynamodb
fn delete_session_in_ddb(dynamodb: &amp;amp;DynamoDbClient, sessid: &amp;amp;String) {
    let applogger = &amp;amp;LOGGING.logger;
    let av = AttributeValue {
        s: Some(sessid.clone()),
        ..Default::default()
    };
    let mut key = HashMap::new();
    key.insert("sessid".to_string(), av);
    let delete_item_input = DeleteItemInput {
        table_name: "session".to_string(),
        key: key,
        ..Default::default()
    };
    match dynamodb.delete_item(delete_item_input).sync() {
        Ok(_) =&amp;gt; {
            debug!(applogger, "Deleted invalid session from ddb";
                "sessid" =&amp;gt; sessid);
        }
        Err(e) =&amp;gt; {
            crit!(applogger, "Error in dynamodb"; "err" =&amp;gt; e.to_string());
            panic!("Error in dynamodb: {}", e.to_string());
        }
    };
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Lots, lots, lots more to do – but I’m having fun with this. It might go faster if I actually had a plan for what this web app actually does. I mean, I have an idea, but I haven’t mocked up a single page so I’m going slow and just enjoying hacking out &lt;code&gt;Rust&lt;/code&gt; code as I go! Thanks for coming along with me!&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://rust.graystorm.com/2019/08/04/rust-web-app-session-management-with-aws/"&gt;Rust Web App Session Management with AWS&lt;/a&gt; appeared first on &lt;a href="https://rust.graystorm.com"&gt;Learning Rust&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>beginners</category>
      <category>aws</category>
      <category>webapp</category>
    </item>
    <item>
      <title>Rust Functions, Modules, Packages, Crates, and You</title>
      <dc:creator>Jeff Culverhouse</dc:creator>
      <pubDate>Tue, 23 Jul 2019 13:00:07 +0000</pubDate>
      <link>https://forem.com/jculverhouse/rust-functions-modules-packages-crates-and-you-47hl</link>
      <guid>https://forem.com/jculverhouse/rust-functions-modules-packages-crates-and-you-47hl</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi1.wp.com%2Frust.graystorm.com%2Fwp-content%2Fuploads%2F2019%2F07%2Fwood-wall-beam-transport-pile-industrial-1358094-pxhere.com_.jpg%3Ffit%3D840%252C560%26ssl%3D1" 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%2Fi1.wp.com%2Frust.graystorm.com%2Fwp-content%2Fuploads%2F2019%2F07%2Fwood-wall-beam-transport-pile-industrial-1358094-pxhere.com_.jpg%3Ffit%3D840%252C560%26ssl%3D1" alt="Wooden pallets stacked one on top another"&gt;&lt;/a&gt;I know the code is in here… somewhere.&lt;/p&gt;

&lt;p&gt;Come to find out, I’m learning Rust from old documentation. Both of the printed Rust books I have are for the pre-“2018 edition” and I think that’s contributing to some confusion I have about functions, modules, packages, and crates. A new version of the official book is coming out in the next month or so – I have a link to it through Amazon in the right sidebar. If you’ve been reading the &lt;a href="https://doc.rust-lang.org/book/" rel="noopener noreferrer"&gt;online documentation&lt;/a&gt;, you’re ok – it is updated fir the “2018-edition”. I’ve looked at some of these &lt;a href="https://rust.graystorm.com/2019/07/10/rust-functions-methods-and-traits/" rel="noopener noreferrer"&gt;parts of Rust&lt;/a&gt; before, but I recently found another new resource, the &lt;a href="https://doc.rust-lang.org/edition-guide/" rel="noopener noreferrer"&gt;Edition Guide&lt;/a&gt;, which clears up some of my issues. Especially of interest here, is the section on &lt;a href="https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-clarity.html" rel="noopener noreferrer"&gt;Path Clarity&lt;/a&gt; which heavily influenced by &lt;a href="https://github.com/rust-lang/rfcs/blob/master/text/2126-path-clarity.md" rel="noopener noreferrer"&gt;RFC 2126&lt;/a&gt; that improved this part of Rust.&lt;/p&gt;

&lt;p&gt;I learned some of the history (and excitement) of RFC 2126 while listening to the &lt;a href="https://podcast.app/two-paths-diverged-in-a-yellow-wood-e22953523/" rel="noopener noreferrer"&gt;Request for Explanation podcast, episode 10&lt;/a&gt;. Anyway, let’s go back to basics and have a look at Rust functions, modules, packages and crates as the language sits in mid-2019. I’ll present some examples from my web application we’ve been looking at. I’m going to cut out unnecessary bits to simplify things, so a “…” means there was more there in order for this to compile. You can always see whatever state it happens to be in, &lt;a href="https://github.com/jculverhouse/pinpoint_shooting" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Crates and Packages
&lt;/h2&gt;

&lt;p&gt;A Rust &lt;strong&gt;crate&lt;/strong&gt; (like Rocket or Diesel) is a binary or library of compiled code. A &lt;code&gt;binary crate&lt;/code&gt; is runnable while a &lt;code&gt;library crate&lt;/code&gt; is used for its functionality by being linked with another binary. A &lt;strong&gt;package&lt;/strong&gt; (like my web app) ties together one or more &lt;strong&gt;crates&lt;/strong&gt; with a single &lt;code&gt;Cargo.toml&lt;/code&gt; file. The toml file configures the &lt;strong&gt;package&lt;/strong&gt; ‘s dependencies and some minimal information about compiling the source. A &lt;code&gt;binary crate&lt;/code&gt; will have a &lt;code&gt;src/main.rs&lt;/code&gt; with a &lt;code&gt;main()&lt;/code&gt; function which directs how the binary runs. A &lt;code&gt;library crate&lt;/code&gt; will have a &lt;code&gt;src/lib.rs&lt;/code&gt; which is the top layer of the library. This top layer directs which pieces inside are available to users of the library.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rust Functions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Functions&lt;/strong&gt; are easy – subroutines in your source code. A function starts with &lt;code&gt;fn&lt;/code&gt;, possibly receives some parameters and might return a value. Also, a function may be scoped as public or kept private. The &lt;code&gt;main()&lt;/code&gt; function inside &lt;code&gt;src/main.rs&lt;/code&gt; is a special function that runs when the binary is called from the command line. It dictates the start of your program and you take control from there. You may create other functions, just avoid reserved words (or use the &lt;code&gt;r#&lt;/code&gt; prefix to indicate you mean YOUR function, not the reserved word, for instance &lt;code&gt;r#expect&lt;/code&gt; if you want to name a function “expect”). Very similar to functions, are methods and traits, which we’ve &lt;a href="https://rust.graystorm.com/2019/07/10/rust-functions-methods-and-traits/" rel="noopener noreferrer"&gt;looked at before&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;src/lib.rs&amp;gt;

...
use diesel::prelude::*;
...
pub fn setup_db() -&amp;gt; PgConnection {
    PgConnection::establish(&amp;amp;CONFIG.database_url)
        .expect(&amp;amp;format!("Error connecting to db"))
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;setup_db()&lt;/code&gt; is a fairly simple function – it accepts no incoming parameters and returns a database connection &lt;code&gt;struct&lt;/code&gt; called &lt;code&gt;PgConnection&lt;/code&gt;. It has &lt;code&gt;pub&lt;/code&gt; before &lt;code&gt;fn&lt;/code&gt; to indicate it is a “public” function. Without that, my web application &lt;code&gt;bin/src/pps.rs&lt;/code&gt; could not call this function – it would not be in scope. Without &lt;code&gt;pub&lt;/code&gt;, &lt;code&gt;setup_db()&lt;/code&gt; would only be callable from &lt;em&gt;within&lt;/em&gt; &lt;code&gt;src/lib.rs&lt;/code&gt;. Since I am designing my application as a &lt;code&gt;library crate&lt;/code&gt;, I choose to put &lt;code&gt;setup_db()&lt;/code&gt; in the main &lt;code&gt;src/lib.rs&lt;/code&gt; file. My binary that I will use to “run” my web application is in &lt;code&gt;src/bin/pps.rs&lt;/code&gt; and contains a &lt;code&gt;main()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Let’s look at the return type, &lt;code&gt;PgConnection&lt;/code&gt;. This is a &lt;code&gt;struct&lt;/code&gt; &lt;a href="https://docs.diesel.rs/diesel/prelude/" rel="noopener noreferrer"&gt;defined&lt;/a&gt; by the database ORM library crate, &lt;a href="https://diesel.rs/" rel="noopener noreferrer"&gt;Diesel&lt;/a&gt;. The only way I could write a function that returns this particular type of &lt;code&gt;struct&lt;/code&gt; is because I have &lt;code&gt;use diesel::prelude::*;&lt;/code&gt; at the top (and it’s in the toml file as well). The Diesel library crate provides &lt;a href="https://docs.diesel.rs/diesel/prelude/" rel="noopener noreferrer"&gt;prelude&lt;/a&gt; as a simple way to bring in all Diesel has to offer my package. Diesel provides the &lt;code&gt;PgConnection&lt;/code&gt; struct as &lt;code&gt;public&lt;/code&gt; (or what good would the &lt;code&gt;crate&lt;/code&gt; be), so I can now use that &lt;code&gt;struct&lt;/code&gt; in my code. This also gives me the (method or trait, how can you tell?) &lt;code&gt;establish()&lt;/code&gt;. Just like you’d call &lt;code&gt;String::new()&lt;/code&gt; for a new string, I’m calling &lt;code&gt;PgConnection::establish()&lt;/code&gt; for a new database connection and then returning it (see, no trailing ; on the line).&lt;/p&gt;

&lt;h2&gt;
  
  
  Rust Modules
&lt;/h2&gt;

&lt;p&gt;Functions (and other things) can be grouped together into a &lt;strong&gt;Module&lt;/strong&gt;. For instance, &lt;code&gt;setup_logging()&lt;/code&gt; is also in &lt;code&gt;src/lib.rs&lt;/code&gt;. However, I could have wrapped it inside a named &lt;code&gt;module&lt;/code&gt;, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;src/lib.rs&amp;gt;

...
pub mod setting_up {
...
    use logging::LOGGING;
    use settings::CONFIG;
    pub fn setup_logging() {
        let applogger = &amp;amp;LOGGING.logger;
        let run_level = &amp;amp;CONFIG.server.run_level;
        warn!(applogger, "Service starting"; "run_level" =&amp;gt; run_level);
     }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it is part of my &lt;code&gt;setting_up&lt;/code&gt; module. Here also, the module needs to be &lt;code&gt;pub&lt;/code&gt; so that my application can use it and the public functions inside it. Now all of the enums and structs and functions inside the module &lt;code&gt;setting_up&lt;/code&gt; are contained together. As long as they are public, I can still get to them in my application.&lt;/p&gt;

&lt;p&gt;Notice I &lt;code&gt;use logging::LOGGING;&lt;/code&gt; and &lt;code&gt;use settings::CONFIG;&lt;/code&gt; These bring in those two &lt;code&gt;structs&lt;/code&gt; so I can use the global statics that are built when then the application starts. I included &lt;code&gt;pub mod logging;&lt;/code&gt; and &lt;code&gt;pub mod settings;&lt;/code&gt; at the top level, in &lt;code&gt;src/lib.rs&lt;/code&gt;, so they are available anyplace deeper in my app. I just need to &lt;code&gt;use&lt;/code&gt; them since I reference them in this module’s code.&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%2Fi2.wp.com%2Frust.graystorm.com%2Fwp-content%2Fuploads%2F2019%2F07%2Fbranch-sharp-wood-warm-trunk-tool-1233390-pxhere.com_.jpg%3Fresize%3D512%252C342%26ssl%3D1" 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%2Fi2.wp.com%2Frust.graystorm.com%2Fwp-content%2Fuploads%2F2019%2F07%2Fbranch-sharp-wood-warm-trunk-tool-1233390-pxhere.com_.jpg%3Fresize%3D512%252C342%26ssl%3D1" alt="Splitting firewood with an axe"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Split, for Clarity
&lt;/h2&gt;

&lt;p&gt;On the other hand, instead of defining a module, or multiple modules, inside a single file like above, you can use a different file to signify a module. This helps split out and separate your code, making it easier to take in a bit at a time. I did that here, with &lt;code&gt;logging.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;src/logging.rs&amp;gt;

...
use slog::{FnValue, *};

pub struct Logging {
    pub logger: slog::Logger,
}

pub static LOGGING: Lazy&amp;lt;Logging&amp;gt; = Lazy::new(|| {
    let logconfig = &amp;amp;CONFIG.logconfig;
    let logfile = &amp;amp;logconfig.applog_path;

    let file = OpenOptions::new()
        .create(true)
        .write(true)
        .truncate(true)
        .open(logfile)
        .unwrap();
    let applogger = slog::Logger::root(
        Mutex::new(slog_bunyan::default(file)).fuse(),
        o!("location" =&amp;gt; FnValue(move |info| {
            format!("{}:{} {}", info.file(), info.line(), info.module(), )
          })
        ),
    );
    Logging { logger: applogger } });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have a &lt;code&gt;struct&lt;/code&gt; and a &lt;code&gt;static&lt;/code&gt; instance of it, both of them public, defined in &lt;code&gt;logging.rs&lt;/code&gt;. &lt;code&gt;logging.rs&lt;/code&gt; becomes a module of my library crate when I specify it. At the top of &lt;code&gt;src/lib.rs&lt;/code&gt; I have &lt;code&gt;pub mod logging;&lt;/code&gt; which indicates my library crate uses that module file &lt;code&gt;logging.rs&lt;/code&gt; &lt;strong&gt;and&lt;/strong&gt; “exports” what it gets from that module as public (so my &lt;code&gt;bin/src/pps.rs&lt;/code&gt; application can use what it provides).&lt;/p&gt;

&lt;p&gt;In this case, you also see I &lt;code&gt;use slog::{FnValue, *}};&lt;/code&gt; which is like &lt;code&gt;use slog::FnValue;&lt;/code&gt; (which I need for the &lt;code&gt;FnValue struct&lt;/code&gt;) and &lt;code&gt;use slog::*;&lt;/code&gt; which gives me the &lt;code&gt;fuse struct&lt;/code&gt; and the &lt;code&gt;o!&lt;/code&gt; macro. I was able to combine those into a single &lt;code&gt;use&lt;/code&gt; statement to get just what I needed from that external &lt;code&gt;crate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The old books I have been referencing have you declaring the third-party &lt;code&gt;crates&lt;/code&gt; you want to use in your application in your &lt;code&gt;Cargo.toml&lt;/code&gt; file (which is still required), but also you’d have to bring each one in with an &lt;code&gt;extern crate each_crate;&lt;/code&gt; at the top of &lt;code&gt;main.rs&lt;/code&gt; or &lt;code&gt;lib.rs&lt;/code&gt;. Thankfully, that’s no longer needed… 99% of the time. In fact, I had a long list of those myself – I am surprised &lt;code&gt;cargo build&lt;/code&gt; didn’t warn me it was unneeded. Actually, I do have one &lt;code&gt;crate&lt;/code&gt; I am using which still needs this “2015-edition” requirement: Diesel. Apparently, it is doing some fancy macro work and/or hasn’t been upgraded (yet?) for the “2018-edition” of Rust, so at the top of &lt;code&gt;src/lib.rs&lt;/code&gt;, I have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#[macro_use]
extern crate diesel;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A Few Standards and TOMLs
&lt;/h2&gt;

&lt;p&gt;The Rust crate &lt;code&gt;std&lt;/code&gt; is the &lt;a href="https://doc.rust-lang.org/std/" rel="noopener noreferrer"&gt;standard library&lt;/a&gt;, and is included automatically. The primitive data types and a healthy list of macros and keywords are all included. But, if you need &lt;a href="https://doc.rust-lang.org/std/fs/index.html" rel="noopener noreferrer"&gt;filesystem tools&lt;/a&gt;: &lt;code&gt;use std::fs&lt;/code&gt;; and if you need a &lt;a href="https://doc.rust-lang.org/std/collections/struct.HashMap.html" rel="noopener noreferrer"&gt;HashMap&lt;/a&gt; variable, you’ll need to use &lt;code&gt;std::collections::HashMap;&lt;/code&gt; And yes, all external crates you depend on inside your source will need to be listed in &lt;code&gt;Cargo.toml&lt;/code&gt;. This configuration helps you though – it updates &lt;code&gt;crates&lt;/code&gt; automatically as minor versions become available, but does NOT update if a major version is released. You will need to do that manually, so you can test to see if the major release broke anything you depended on in your code. Here is a piece of my ever-growing &lt;code&gt;Cargo.toml&lt;/code&gt; file for the web application so far:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
[dependencies]
    slog = "2.5.0"
    slog-bunyan = "2.1.0"
    base64 = "0.10.1"
    rand = "0.7.0"
    rand_core = "0.5.0"
    rust-crypto = "0.2.36"
    config = "0.9.3"
    serde = "1.0.94"
    serde_derive = "1.0.94"
    serde_json = "1.0.40"
    once_cell = "0.2.2"
    dotenv = "0.14.1"
    chrono = "0.4.7"
    rocket = "0.4.2"
    rocket-slog = "0.4.0"

[dependencies.diesel]
    version = "1.4.2"
    features = ["postgres","chrono"]

[dependencies.rocket_contrib]
    version = "0.4.2"
    default-features = false
    features = ["serve","handlebars_templates","helmet","json"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The post &lt;a href="https://rust.graystorm.com/2019/07/23/more-on-rust-functions-modules-packages-and-crates/" rel="noopener noreferrer"&gt;Rust Functions, Modules, Packages, Crates, and You&lt;/a&gt; appeared first on &lt;a href="https://rust.graystorm.com" rel="noopener noreferrer"&gt;Learning Rust&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Better Logging for the Web Application</title>
      <dc:creator>Jeff Culverhouse</dc:creator>
      <pubDate>Sat, 20 Jul 2019 14:00:14 +0000</pubDate>
      <link>https://forem.com/jculverhouse/better-logging-for-the-web-application-2emb</link>
      <guid>https://forem.com/jculverhouse/better-logging-for-the-web-application-2emb</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi2.wp.com%2Frust.graystorm.com%2Fwp-content%2Fuploads%2F2019%2F07%2Fwriting-retro-number-old-pattern-line-613428-pxhere.com_.jpg%3Fssl%3D1" 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%2Fi2.wp.com%2Frust.graystorm.com%2Fwp-content%2Fuploads%2F2019%2F07%2Fwriting-retro-number-old-pattern-line-613428-pxhere.com_.jpg%3Fssl%3D1" alt="A journal ledger of accounts... like logging but only uses numbers"&gt;&lt;/a&gt;See… structured logging…&lt;/p&gt;

&lt;p&gt;When I last &lt;a href="https://rust.graystorm.com/2019/07/15/its-not-a-web-application-without-a-database/" rel="noopener noreferrer"&gt;left my sample web application&lt;/a&gt;, I was doing simple logging to the terminal which is not useful for very long. I want &lt;a href="https://stackify.com/what-is-structured-logging-and-why-developers-need-it/" rel="noopener noreferrer"&gt;structured logging&lt;/a&gt; and I want the app and &lt;code&gt;Rocket&lt;/code&gt; to write to (separate) files. So, let’s switch out the crates &lt;code&gt;log&lt;/code&gt; and &lt;code&gt;simple_log&lt;/code&gt; for &lt;code&gt;slog&lt;/code&gt; and &lt;code&gt;sloggers&lt;/code&gt; to get better logging for my web application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Application Logging
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://crates.io/crates/slog" rel="noopener noreferrer"&gt;Slog&lt;/a&gt;‘s “ambition is to be The Logging Library for Rust” and it sure seems adaptable. There are several “helper” crates to log to the terminal or syslog, log as json, etc. However, &lt;code&gt;slog&lt;/code&gt; is complex! Which seems to be the main reason &lt;code&gt;sloggers&lt;/code&gt; came about. &lt;code&gt;Sloggers&lt;/code&gt; brings you the most useful features of &lt;code&gt;slog&lt;/code&gt; without the complex setup. It happens to include an example of configuring via an inline TOML string. I’ve already got my &lt;code&gt;CONFIG&lt;/code&gt; global pulling from a TOML file, so I add this to &lt;code&gt;conf/development.toml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;conf/development.toml&amp;gt;

...
[logconfig]
type = "file"
format = "compact"
source_location = "module_and_line"
timezone = "local"
level = "debug"
path = "log/error.log"
rotate_size = 1073741824
rotate_keep = 2

[webservice]
weblog_path = "log/access.log"
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plus, I add &lt;code&gt;logging.rs&lt;/code&gt; to set up the global &lt;code&gt;LOGGING&lt;/code&gt; instance so everyone can log; just like everyone can pull from the global &lt;code&gt;CONFIG&lt;/code&gt; instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;logging.rs&amp;gt;

use crate::settings::CONFIG;
use crate::sloggers::{Build, Config};
use once_cell::sync::Lazy;

#[derive(Debug)]
pub struct Logging {
    pub logger: slog::Logger,
}

pub static LOGGING: Lazy&amp;lt;Logging&amp;gt; = Lazy::new(|| {
    let logconfig = &amp;amp;CONFIG.logconfig;
    let builder = logconfig.try_to_builder().unwrap();
    let logger = builder.build().unwrap();

    Logging { logger: logger }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Sloggers&lt;/code&gt; is really easy to use to set up a &lt;code&gt;slog&lt;/code&gt; instance. Here, I simply pull the logconfig from my global &lt;code&gt;CONFIG&lt;/code&gt;, build the logger, and store it in my new &lt;a href="https://crates.io/crates/once_cell" rel="noopener noreferrer"&gt;OnceCell&lt;/a&gt; Lazy &lt;code&gt;LOGGING&lt;/code&gt; global.&lt;/p&gt;

&lt;h2&gt;
  
  
  And then, Web Access Logging
&lt;/h2&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%2Fi0.wp.com%2Frust.graystorm.com%2Fwp-content%2Fuploads%2F2019%2F07%2Fnature-dew-wing-morning-fauna-material-792967-pxhere.com_.jpg%3Fssl%3D1" 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%2Fi0.wp.com%2Frust.graystorm.com%2Fwp-content%2Fuploads%2F2019%2F07%2Fnature-dew-wing-morning-fauna-material-792967-pxhere.com_.jpg%3Fssl%3D1" alt="A spider web, wet from rain...&amp;lt;br&amp;gt;
"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point, application logging is going to my new &lt;code&gt;log/error.log&lt;/code&gt; file, but &lt;code&gt;Rocket&lt;/code&gt; logging is still coming to the screen. This is actually good – as I mentioned, I want to have them going to separate files anyway. So now with some &lt;code&gt;slogging&lt;/code&gt; experience, it’s a simple matter to set up a second file, specifically for &lt;code&gt;Rocket&lt;/code&gt;. I do need to add yet another crate, this time &lt;a href="https://crates.io/crates/rocket-slog" rel="noopener noreferrer"&gt;rocket_slog&lt;/a&gt; – so that &lt;code&gt;Rocket&lt;/code&gt; internals can glom on to the &lt;code&gt;slog&lt;/code&gt; instance that I make. Here is the new &lt;code&gt;start_webservice&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;src/lib.src&amp;gt;

...
pub fn start_webservice() {
    let logger = &amp;amp;LOGGING.logger;
    let weblog_path = &amp;amp;CONFIG.webservice.weblog_path;
    let bind_address = &amp;amp;CONFIG.webservice.bind_address;
    let bind_port = &amp;amp;CONFIG.webservice.bind_port;

    // start rocket webservice
    let version = include_str!("version.txt");
    let mut builder = FileLoggerBuilder::new(weblog_path);

    builder.level(Severity::Debug);

    let weblogger = builder.build().unwrap();
    let fairing = SlogFairing::new(weblogger);
    warn!(logger, "Waiting for connections...";
        "address" =&amp;gt; bind_address,
        "port" =&amp;gt; bind_port,
        "version" =&amp;gt; version);

    rocket::ignite()
        .attach(fairing)
        .attach(Template::fairing())
        .attach(SpaceHelmet::default())
        .mount("/", routes![routes::index, routes::favicon])
        .mount("/img", StaticFiles::from("src/view/static/img"))
        .mount("/css", StaticFiles::from("src/view/static/css"))
        .mount("/js", StaticFiles::from("src/view/static/js"))
        .launch();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I have &lt;code&gt;log/error.log&lt;/code&gt; for application logging (I’ll rename that later to &lt;code&gt;log/app.log&lt;/code&gt;) and &lt;code&gt;log/access.log&lt;/code&gt; for &lt;code&gt;Rocket&lt;/code&gt; logging. But I still don’t have structured logs!&lt;/p&gt;

&lt;h2&gt;
  
  
  Finally, Structured Logs
&lt;/h2&gt;

&lt;p&gt;I try several ways (with my limited Rust knowledge and experience) but it appears that with &lt;code&gt;sloggers&lt;/code&gt; ease of use, you trade away options if you want to get fancy. At least, &lt;strong&gt;I&lt;/strong&gt; couldn’t figure out how to get &lt;code&gt;slog_json&lt;/code&gt; or something called &lt;code&gt;slog_bunyan&lt;/code&gt; to work with &lt;code&gt;sloggers&lt;/code&gt;. It looks like I have to deal with &lt;code&gt;slog&lt;/code&gt; directly.&lt;/p&gt;

&lt;p&gt;Later, on another night, I tackle these changes. I dump &lt;code&gt;sloggers&lt;/code&gt; and, though much searching around, I end up with a merge of two examples I find (from &lt;code&gt;slog&lt;/code&gt; and &lt;code&gt;slog&lt;/code&gt;-bunyan). Thankfully, I am getting a little better at understanding the API docs that are posted for crates! Anyway, here is how the app logging setup looks now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;src/logging.rs&amp;gt;

...
pub static LOGGING: Lazy&amp;lt;Logging&amp;gt; = Lazy::new(|| {
    let logconfig = &amp;amp;CONFIG.logconfig;
    let logfile = &amp;amp;logconfig.applog_path;
    let file = OpenOptions::new()
        .create(true)
        .write(true)
        .truncate(true)
        .open(logfile)
        .unwrap();
    let applogger = slog::Logger::root(
        Mutex::new(slog_bunyan::default(file)).fuse(),
        o!("location" =&amp;gt; FnValue(move |info| {
            format!("{}:{} {}", info.file(), info.line(), info.module(), )
          })
        ),
    );
    Logging { logger: applogger } });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice I still pull the &lt;code&gt;applog_path&lt;/code&gt; from the &lt;code&gt;CONFIG&lt;/code&gt; and then create that filehandle. Next, a single but complicated call into &lt;code&gt;slog&lt;/code&gt; returns a &lt;code&gt;Logger&lt;/code&gt; instance, which I store into my global. The &lt;code&gt;o!&lt;/code&gt; macro, provided by the &lt;code&gt;slog&lt;/code&gt; &lt;code&gt;crate&lt;/code&gt;, lets me add a JSON field to every log record that gets written. I copy from an example and add the file, line number, and module name where the log was generated. I’ll probably come back to this later and add more data. Also, notice I am using &lt;a href="https://crates.io/crates/slog-bunyan" rel="noopener noreferrer"&gt;slog_bunyan&lt;/a&gt; for the JSON formatting. &lt;code&gt;slog-json&lt;/code&gt; actually recommends using &lt;code&gt;slog_bunyan&lt;/code&gt; for a “more complete output format.” &lt;a href="https://nodejs.org/es/blog/module/service-logging-in-json-with-bunyan/" rel="noopener noreferrer"&gt;Bunyan logging&lt;/a&gt; seems to originate as a node.js module. Lastly, I also change the weblogger in the same way – now both are JSON logs and still log to separate files.&lt;/p&gt;

&lt;p&gt;This actually wasn’t as complicated as I feared. I’ve lost some of the easily configurable &lt;code&gt;sloggers&lt;/code&gt; features like auto file rotation, but I’ll figure that out as well – it’s probably actually just a &lt;code&gt;slog&lt;/code&gt; feature that I need to enable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results, JSON Style
&lt;/h2&gt;

&lt;p&gt;Here is how both look now – I think next post I’ll work on a JSON log viewer so we can watch these easier, as we develop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;log/app.log&amp;gt;

{"msg":"Service starting","v":0,"name":"slog-rs","level":40,"time":"2019-07-20T03:40:13.781382592+00:00","hostname":"ip-169-254-169-254","pid":6368,"location":"src/lib.rs:48 ppslib","run_level":"development"}
{"msg":"Waiting for connections...","v":0,"name":"slog-rs","level":40,"time":"2019-07-20T03:40:13.784899718+00:00","hostname":"ip-169-254-169-254","pid":6368,"location":"src/lib.rs:76 ppslib","version":"0.1.0","port":3000,"address":"0.0.0.0"}

&amp;lt;log/access.log&amp;gt;

{"msg":"listening","v":0,"name":"slog-rs","level":30,"time":"2019-07-20T05:31:21.068959173+00:00","hostname":"ip-169-254-169-254","pid":7700,"address":"http://0.0.0.0:3000"}
{"msg":"request","v":0,"name":"slog-rs","level":30,"time":"2019-07-20T05:31:22.402815352+00:00","hostname":"ip-169-254-169-254","pid":7700,"uri":"\"/\"","method":"Get"}
{"msg":"response","v":0,"name":"slog-rs","level":30,"time":"2019-07-20T05:31:22.404425952+00:00","hostname":"ip-169-254-169-254","pid":7700,"status":"200 OK","route":"\u001b[32mGET\u001b[0m \u001b[34m/\u001b[0m \u001b[36m(\u001b[0m\u001b[35mindex\u001b[0m\u001b[36m)\u001b[0m"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, if all that was complicated to follow and you prefer to look at the git commits as I went through this ordeal, check out the &lt;a href="https://github.com/jculverhouse/pinpoint_shooting" rel="noopener noreferrer"&gt;repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://rust.graystorm.com/2019/07/20/better-logging-for-the-web-application/" rel="noopener noreferrer"&gt;Better Logging for the Web Application&lt;/a&gt; appeared first on &lt;a href="https://rust.graystorm.com" rel="noopener noreferrer"&gt;Learning Rust&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>webapp</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Using Match – Bob Revisited</title>
      <dc:creator>Jeff Culverhouse</dc:creator>
      <pubDate>Wed, 17 Jul 2019 14:00:28 +0000</pubDate>
      <link>https://forem.com/jculverhouse/using-match-bob-revisited-2jc4</link>
      <guid>https://forem.com/jculverhouse/using-match-bob-revisited-2jc4</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi2.wp.com%2Frust.graystorm.com%2Fwp-content%2Fuploads%2F2019%2F07%2Fboard-games-encouragement-games-scrabble-spell-spelling-1520271-pxhere.com_.jpg%3Ffit%3D840%252C461%26ssl%3D1" 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%2Fi2.wp.com%2Frust.graystorm.com%2Fwp-content%2Fuploads%2F2019%2F07%2Fboard-games-encouragement-games-scrabble-spell-spelling-1520271-pxhere.com_.jpg%3Ffit%3D840%252C461%26ssl%3D1" alt="TRY AGAIN in Scrabble letter - as I try again with an Exercism task, this time using match."&gt;&lt;/a&gt;Wait, “TG”? That's not a word! Challenge!&lt;/p&gt;

&lt;p&gt;Remember Bob from a &lt;a href="https://rust.graystorm.com/2019/07/01/return-to-string-basics/" rel="noopener noreferrer"&gt;previous post&lt;/a&gt; – our tiniest of AI-responders? I got feedback from the &lt;a href="https://exercism.io/" rel="noopener noreferrer"&gt;Exercism&lt;/a&gt; tutor that I had avoided one of &lt;code&gt;Rust&lt;/code&gt;'s most versatile of operators and I should think about using match. So, not to be a jerk, but just to see if I could replace ALL of the &lt;code&gt;if&lt;/code&gt;s in my method, I quickly came up with this solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Switch to Using Match
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pub fn reply(message: &amp;amp;str) -&amp;gt; &amp;amp;str {
    let message = message.trim();
    let question = message.ends_with('?');
    let any_alpha = message.chars().any(char::is_alphabetic);
    let is_yelling = message.to_ascii_uppercase() == message;
    let is_empty = message.len() == 0;
    match message.is_empty() {
        true =&amp;gt; "Fine. Be that way!",
        _ =&amp;gt; match any_alpha &amp;amp;&amp;amp; is_yelling {
            true =&amp;gt; match question {
                true =&amp;gt; "Calm down, I know what I'm doing!",
                _ =&amp;gt; "Whoa, chill out!",
            },
            _ =&amp;gt; match !is_empty &amp;amp;&amp;amp; question {
                true =&amp;gt; "Sure.",
                _ =&amp;gt; "Whatever.",
            },
        },
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Come On Bob, Get With the Rust
&lt;/h2&gt;

&lt;p&gt;So, it may be my newness to Rust, but I’m not sure version 2 is “more maintainable” code than what I started with. I had thought this Exercism task was just about learning some string methods. Turns out, it is also about learning the &lt;code&gt;match&lt;/code&gt; operator. Of course, you wouldn’t code any parser or AI this way anyway – this IS just for practice.&lt;/p&gt;

&lt;p&gt;Another tiny thing the tutor pointed out, I did have &lt;code&gt;let check_message = message.trim()&lt;/code&gt; in my earlier code. A more idiomatic way in Rust is to reassign it to the same variable, hence the &lt;code&gt;let message = message.trim()&lt;/code&gt; in this version. My guess is: less memory allocation, fewer variables for you to keep track of, and you aren’t able to incorrectly use the wrong variable later in the method. Actually, that probably isn’t a Rust idea – that’s just a good programming tip.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bob With a Trait
&lt;/h2&gt;

&lt;p&gt;Patterns are, I'm told, very powerful in Rust and that's a big reason to start using &lt;code&gt;match&lt;/code&gt; wherever you can. I’ve also learned a bit about &lt;code&gt;traits&lt;/code&gt; and &lt;code&gt;impls&lt;/code&gt; which I talked about in an &lt;a href="https://rust.graystorm.com/2019/07/10/rust-functions-methods-and-traits/" rel="noopener noreferrer"&gt;earlier post&lt;/a&gt;. And that got me thinking maybe I’d work through the syntax to get it working with a &lt;code&gt;trait&lt;/code&gt; instead. That idea led to this code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pub fn reply(message: &amp;amp;str) -&amp;gt; &amp;amp;str {
    enum Quality {
        Empty,
        YellQuestion,
        YellStatement,
        AskQuestion,
        Statement, };

    trait HasQuality {
        fn has_quality(&amp;amp;self) -&amp;gt; Quality;
    }

    impl HasQuality for str {
        fn has_quality(&amp;amp;self) -&amp;gt; Quality {
            let message = self.trim();
            let question = message.ends_with('?');
            let any_alpha = message.chars().any(char::is_alphabetic);
            let is_yelling = message.to_ascii_uppercase() == message;
            let is_empty = message.len() == 0;

            match message.is_empty() {
                true =&amp;gt; Quality::Empty,
                _ =&amp;gt; match any_alpha &amp;amp;&amp;amp; is_yelling {
                    true =&amp;gt; match question {
                        true =&amp;gt; Quality::YellQuestion,
                        _ =&amp;gt; Quality::YellStatement,
                    },
                    _ =&amp;gt; match !is_empty &amp;amp;&amp;amp; question {
                        true =&amp;gt; Quality::AskQuestion,
                        _ =&amp;gt; Quality::Statement,
                    },
                },
            }
        }
    };
    match message.has_quality() {
        Quality::Empty =&amp;gt; "Fine. Be that way!",
        Quality::YellQuestion =&amp;gt; "Calm down, I know what I'm doing!",
        Quality::YellStatement =&amp;gt; "Whoa, chill out!",
        Quality::AskQuestion =&amp;gt; "Sure.",
        _ =&amp;gt; "Whatever.",
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So here, we come up with the idea of a Quality &lt;code&gt;trait&lt;/code&gt; and then we implement that &lt;code&gt;trait&lt;/code&gt; for the built-in &lt;code&gt;str&lt;/code&gt; primitive. We’ve expanded what you can do to a &lt;code&gt;str&lt;/code&gt; with our own &lt;code&gt;trait&lt;/code&gt;! Version 3 of Bob really helps reveal some of the Rust thought patterns I need to hone.&lt;/p&gt;

&lt;p&gt;Of course, I made sure Version 3 still passes all of the Exercism tests for this task. This change was approaching my limit of Rust knowledge to get it working without help from a book – just obeying every compiler complaint. However, I cranked this out much faster than previous Rust code, so I think some of this learning (and blogging) is sinking in! I surprised myself enough, that I &lt;a href="https://exercism.io/tracks/rust/exercises/bob/solutions/ea9b6aab73c249e5b7710d5c705da7c7" rel="noopener noreferrer"&gt;posted this solution to Exercism&lt;/a&gt; as well. I want to hear what the tutor has to say about this method (no pun intended!). Now, I just need to remember to keep using match, traits, impls, and other Rust-supplied power!&lt;/p&gt;

&lt;h2&gt;
  
  
  Update: 2019-07-17 13:30
&lt;/h2&gt;

&lt;p&gt;Woah, I just got some great advice from the Exercism tutor! You can &lt;code&gt;match&lt;/code&gt; on a &lt;code&gt;(expression, expression, ...)&lt;/code&gt; so check this out!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;impl HasQuality for str {
    fn has_quality(&amp;amp;self) -&amp;gt; Quality {
        let message = self.trim();
        let question = message.ends_with('?');
        let any_alpha = message.chars().any(char::is\_alphabetic);
        let is_yelling = message.to_ascii_uppercase() == message;
        let is_empty = message.len() == 0;

        match (is_empty, any_alpha &amp;amp;&amp;amp; is_yelling, question) {
            (true, _, _) =&amp;gt; Quality::Empty,
            (false, true, true) =&amp;gt; Quality::YellQuestion,
            (false, true, false) =&amp;gt; Quality::YellStatement,
            (false, false, true) =&amp;gt; Quality::AskQuestion,
            _ =&amp;gt; Quality::Statement,
        }
    }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The post &lt;a href="https://rust.graystorm.com/2019/07/17/using-match-bob-revisited/" rel="noopener noreferrer"&gt;Using Match – Bob Revisited&lt;/a&gt; appeared first on &lt;a href="https://rust.graystorm.com" rel="noopener noreferrer"&gt;Learning Rust&lt;/a&gt;.&lt;/p&gt;

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