Skip to content

Commit

Permalink
Rust-Usage-of-Cow
Browse files Browse the repository at this point in the history
Signed-off-by: Vineel Kovvuri <[email protected]>
  • Loading branch information
vineelkovvuri committed Jan 17, 2025
1 parent deb4a32 commit 8537735
Show file tree
Hide file tree
Showing 51 changed files with 516 additions and 244 deletions.
96 changes: 96 additions & 0 deletions content/blog/Rust-Usage-of-Cow/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
title: "Rust: Usage of Cow(Clone on Write)"
date: 2025-01-17 14:03:43
tags: ['Rust']
---

## Rust: Usage of Cow(Clone on Write)

Today, After reading following blog
post(https://hermanradtke.com/2015/05/29/creating-a-rust-function-that-returns-string-or-str.html/),
I finally understood the need for Cow in Rust. Below is my code sample with
relevant comments.

```rust
use std::borrow::Cow;

#[derive(Clone, Debug)]
struct Book {
name: String,
price: u32,
}

fn update_book_price<'a>(book: &'a Book, price: u32) -> Cow<'a, Book> {
// If the price matches, there's no need to create a new book.
if book.price == price {
return Cow::Borrowed(book);
}

// If the price does not match, create a new book (updating the title to
// make it easy to distinguish the objects).
Cow::Owned(Book {
name: format!("{}-updated", book.name.clone()),
price,
})
}

fn main() {
let book = Book {
name: "Rust programming".to_string(),
price: 100,
};

// CASE 1: Since there is no change in price, we get a `Cow` wrapped
// borrowed version of the existing book.
let updated_book: Cow<'_, Book> = update_book_price(&book, 100);
// The returned `Cow` object is always immutable. The following line will
// not work even though we can access the object fields via the `Deref`
// trait:
// updated_book.price = 200;
println!("{:?}", updated_book); // Book { name: "Rust programming", price: 100 }

// If we ever need to own the above object (e.g., for modifying it), we can
// call `into_owned()` on `Cow` to get a cloned version of the book.
// This cloned object will be mutable.
let mut updated_book: Book = updated_book.into_owned();
updated_book.price = 200;
println!("{:?}", updated_book); // Book { name: "Rust programming", price: 200 }

// ========================================

// CASE 2: Since the price has changed, we get a `Cow` wrapped owned version
// of the book. This owned version is the object we created in the
// `update_book_price()` method.
let updated_book: Cow<'_, Book> = update_book_price(&book, 300);
// Again, the returned object is immutable, so the following line will not
// work:
// updated_book.price = 400;
println!("{:?}", updated_book); // Book { name: "Rust programming-updated", price: 300 }

// If we ever need to own this object (e.g., for modifying it), we can call
// `into_owned()` on `Cow` to get the owned object. Importantly, in this
// case, `Cow` simply returns the already owned object instead of cloning
// it. The returned object will be mutable.
let mut updated_book: Book = updated_book.into_owned();
updated_book.price = 400;
println!("{:?}", updated_book); // Book { name: "Rust programming-updated", price: 400 }

// Takeaway 1: `Cow` allows us to defer cloning a borrowed object until it
// is required for modification (ownership). When ownership is needed, `Cow`
// provides the following behavior via `into_owned()`:
// 1. `Cow` either calls `clone()` on the borrowed object.
// 2. Or, `Cow` directly returns the underlying owned object.

// Takeaway 2: With the help of `Cow` (Clone-On-Write), we can design
// methods optimized to return the borrowed object wrapped inside `Cow`.
// This approach helps delay the cloning process. Specifically, the
// `update_book_price()` method returns either a borrowed `Cow` or an owned
// `Cow`, catering to both cases. However, this flexibility is not always
// necessary. Since every type `T` that `Cow` wraps requires
// `#[derive(Clone)]`, `Cow` can decide when to clone the borrowed object
// and when to return the underlying owned object directly, depending on the
// need when `into_owned()` is called.

// Reference: https://hermanradtke.com/2015/05/29/creating-a-rust-function-that-returns-string-or-str.html/
}
```
2 changes: 1 addition & 1 deletion docs/404.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=9999&amp;path=livereload" data-no-instant defer></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>404 Page not found | Vineel Kovvuri</title>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=9999&amp;path=livereload" data-no-instant defer></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>A Newbie&#39;s Introduction To Compilation Process And Reverse Engineering | Vineel Kovvuri</title>
Expand Down
2 changes: 1 addition & 1 deletion docs/blog/c-case-studies/f/index.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=9999&amp;path=livereload" data-no-instant defer></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Libspng - C Language Case Study | Vineel Kovvuri</title>
Expand Down
2 changes: 1 addition & 1 deletion docs/blog/compiler-internals/index.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=9999&amp;path=livereload" data-no-instant defer></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Compiler Internals | Vineel Kovvuri</title>
Expand Down
2 changes: 1 addition & 1 deletion docs/blog/how-do-breakpoints-work-in-debuggers/index.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=9999&amp;path=livereload" data-no-instant defer></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>How Do Breakpoints Work In Debuggers? | Vineel Kovvuri</title>
Expand Down
7 changes: 6 additions & 1 deletion docs/blog/index.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=9999&amp;path=livereload" data-no-instant defer></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Blogs | Vineel Kovvuri</title>
Expand Down Expand Up @@ -35,6 +35,11 @@ <h1>Blog</h1>



<li>
<span class="date">2025/01/17</span>
<a href="/blog/rust-usage-of-cow/">Rust: Usage of Cow(Clone on Write) - blog</a>
</li>

<li>
<span class="date">2025/01/14</span>
<a href="/blog/rust-from-vs-into-traits-part-2/">Rust: From and Into trait - Part 2 - blog</a>
Expand Down
73 changes: 40 additions & 33 deletions docs/blog/index.xml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/blog/lib-files-101/index.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=9999&amp;path=livereload" data-no-instant defer></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Lib Files 101 | Vineel Kovvuri</title>
Expand Down
2 changes: 1 addition & 1 deletion docs/blog/pci-express-basics-101/index.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=9999&amp;path=livereload" data-no-instant defer></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>PCI Express Basics 101 | Vineel Kovvuri</title>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=9999&amp;path=livereload" data-no-instant defer></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Pdb Files: The Glue Between The Binary File And Source Code | Vineel Kovvuri</title>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=9999&amp;path=livereload" data-no-instant defer></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Rust: Aligned vs Unaligned Memory Access | Vineel Kovvuri</title>
Expand Down
2 changes: 1 addition & 1 deletion docs/blog/rust-from-vs-into-traits-part-2/index.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=9999&amp;path=livereload" data-no-instant defer></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Rust: From and Into trait - Part 2 | Vineel Kovvuri</title>
Expand Down
2 changes: 1 addition & 1 deletion docs/blog/rust-from-vs-into-traits/index.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=9999&amp;path=livereload" data-no-instant defer></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Rust: From vs Into traits | Vineel Kovvuri</title>
Expand Down
2 changes: 1 addition & 1 deletion docs/blog/rust-sharing-objects/index.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=9999&amp;path=livereload" data-no-instant defer></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Rust: Sharing a Single Object Across Multiple Owners | Vineel Kovvuri</title>
Expand Down
Loading

0 comments on commit 8537735

Please sign in to comment.