summaryrefslogtreecommitdiffstats
path: root/src/doc/book/listings/ch17-oop
diff options
context:
space:
mode:
Diffstat (limited to 'src/doc/book/listings/ch17-oop')
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-01/Cargo.lock6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-01/Cargo.toml6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-01/src/lib.rs4
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-02/Cargo.lock6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-02/Cargo.toml6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-02/src/lib.rs33
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-03/Cargo.lock6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-03/Cargo.toml6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-03/src/lib.rs3
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-04/Cargo.lock6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-04/Cargo.toml6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-04/src/lib.rs9
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-05/Cargo.lock6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-05/Cargo.toml6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-05/src/lib.rs17
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-06/Cargo.lock6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-06/Cargo.toml6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-06/src/lib.rs20
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-07/Cargo.lock6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-07/Cargo.toml6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-07/src/lib.rs29
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-08/Cargo.lock6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-08/Cargo.toml6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-08/src/lib.rs27
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-08/src/main.rs17
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-09/Cargo.lock6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-09/Cargo.toml6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-09/src/lib.rs27
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-09/src/main.rs40
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-10/Cargo.lock6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-10/Cargo.toml6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-10/output.txt13
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-10/src/lib.rs27
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-10/src/main.rs9
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-11/Cargo.lock6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-11/Cargo.toml6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-11/src/main.rs20
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-12/Cargo.lock6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-12/Cargo.toml6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-12/src/lib.rs19
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-12/src/main.rs14
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-13/Cargo.lock6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-13/Cargo.toml6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-13/src/lib.rs28
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-13/src/main.rs14
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-14/Cargo.lock6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-14/Cargo.toml6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-14/src/lib.rs32
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-14/src/main.rs14
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-15/Cargo.lock6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-15/Cargo.toml6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-15/src/lib.rs52
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-15/src/main.rs14
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-16/Cargo.lock6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-16/Cargo.toml6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-16/src/lib.rs85
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-16/src/main.rs14
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-17/Cargo.lock6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-17/Cargo.toml6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-17/src/lib.rs82
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-17/src/main.rs14
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-18/Cargo.lock6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-18/Cargo.toml6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-18/src/lib.rs94
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-18/src/main.rs14
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-19/Cargo.lock6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-19/Cargo.toml6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-19/src/lib.rs25
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-20/Cargo.lock6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-20/Cargo.toml6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-20/src/lib.rs48
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-21/Cargo.lock6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-21/Cargo.toml6
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-21/src/lib.rs43
-rw-r--r--src/doc/book/listings/ch17-oop/listing-17-21/src/main.rs13
75 files changed, 1166 insertions, 0 deletions
diff --git a/src/doc/book/listings/ch17-oop/listing-17-01/Cargo.lock b/src/doc/book/listings/ch17-oop/listing-17-01/Cargo.lock
new file mode 100644
index 000000000..471d8dfc3
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-01/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "averaged-collection"
+version = "0.1.0"
+
diff --git a/src/doc/book/listings/ch17-oop/listing-17-01/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-01/Cargo.toml
new file mode 100644
index 000000000..aed614e93
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-01/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "averaged-collection"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/src/doc/book/listings/ch17-oop/listing-17-01/src/lib.rs b/src/doc/book/listings/ch17-oop/listing-17-01/src/lib.rs
new file mode 100644
index 000000000..b5ce2ab64
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-01/src/lib.rs
@@ -0,0 +1,4 @@
+pub struct AveragedCollection {
+ list: Vec<i32>,
+ average: f64,
+}
diff --git a/src/doc/book/listings/ch17-oop/listing-17-02/Cargo.lock b/src/doc/book/listings/ch17-oop/listing-17-02/Cargo.lock
new file mode 100644
index 000000000..471d8dfc3
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-02/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "averaged-collection"
+version = "0.1.0"
+
diff --git a/src/doc/book/listings/ch17-oop/listing-17-02/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-02/Cargo.toml
new file mode 100644
index 000000000..aed614e93
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-02/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "averaged-collection"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/src/doc/book/listings/ch17-oop/listing-17-02/src/lib.rs b/src/doc/book/listings/ch17-oop/listing-17-02/src/lib.rs
new file mode 100644
index 000000000..bb407ec5f
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-02/src/lib.rs
@@ -0,0 +1,33 @@
+pub struct AveragedCollection {
+ list: Vec<i32>,
+ average: f64,
+}
+
+// ANCHOR: here
+impl AveragedCollection {
+ pub fn add(&mut self, value: i32) {
+ self.list.push(value);
+ self.update_average();
+ }
+
+ pub fn remove(&mut self) -> Option<i32> {
+ let result = self.list.pop();
+ match result {
+ Some(value) => {
+ self.update_average();
+ Some(value)
+ }
+ None => None,
+ }
+ }
+
+ pub fn average(&self) -> f64 {
+ self.average
+ }
+
+ fn update_average(&mut self) {
+ let total: i32 = self.list.iter().sum();
+ self.average = total as f64 / self.list.len() as f64;
+ }
+}
+// ANCHOR_END: here
diff --git a/src/doc/book/listings/ch17-oop/listing-17-03/Cargo.lock b/src/doc/book/listings/ch17-oop/listing-17-03/Cargo.lock
new file mode 100644
index 000000000..00d7b2182
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-03/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "gui"
+version = "0.1.0"
+
diff --git a/src/doc/book/listings/ch17-oop/listing-17-03/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-03/Cargo.toml
new file mode 100644
index 000000000..9b816e766
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-03/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "gui"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/src/doc/book/listings/ch17-oop/listing-17-03/src/lib.rs b/src/doc/book/listings/ch17-oop/listing-17-03/src/lib.rs
new file mode 100644
index 000000000..3a5cb779c
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-03/src/lib.rs
@@ -0,0 +1,3 @@
+pub trait Draw {
+ fn draw(&self);
+}
diff --git a/src/doc/book/listings/ch17-oop/listing-17-04/Cargo.lock b/src/doc/book/listings/ch17-oop/listing-17-04/Cargo.lock
new file mode 100644
index 000000000..00d7b2182
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-04/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "gui"
+version = "0.1.0"
+
diff --git a/src/doc/book/listings/ch17-oop/listing-17-04/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-04/Cargo.toml
new file mode 100644
index 000000000..9b816e766
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-04/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "gui"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/src/doc/book/listings/ch17-oop/listing-17-04/src/lib.rs b/src/doc/book/listings/ch17-oop/listing-17-04/src/lib.rs
new file mode 100644
index 000000000..0c45e2a62
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-04/src/lib.rs
@@ -0,0 +1,9 @@
+pub trait Draw {
+ fn draw(&self);
+}
+
+// ANCHOR: here
+pub struct Screen {
+ pub components: Vec<Box<dyn Draw>>,
+}
+// ANCHOR_END: here
diff --git a/src/doc/book/listings/ch17-oop/listing-17-05/Cargo.lock b/src/doc/book/listings/ch17-oop/listing-17-05/Cargo.lock
new file mode 100644
index 000000000..00d7b2182
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-05/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "gui"
+version = "0.1.0"
+
diff --git a/src/doc/book/listings/ch17-oop/listing-17-05/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-05/Cargo.toml
new file mode 100644
index 000000000..9b816e766
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-05/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "gui"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/src/doc/book/listings/ch17-oop/listing-17-05/src/lib.rs b/src/doc/book/listings/ch17-oop/listing-17-05/src/lib.rs
new file mode 100644
index 000000000..57ebb5782
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-05/src/lib.rs
@@ -0,0 +1,17 @@
+pub trait Draw {
+ fn draw(&self);
+}
+
+pub struct Screen {
+ pub components: Vec<Box<dyn Draw>>,
+}
+
+// ANCHOR: here
+impl Screen {
+ pub fn run(&self) {
+ for component in self.components.iter() {
+ component.draw();
+ }
+ }
+}
+// ANCHOR_END: here
diff --git a/src/doc/book/listings/ch17-oop/listing-17-06/Cargo.lock b/src/doc/book/listings/ch17-oop/listing-17-06/Cargo.lock
new file mode 100644
index 000000000..00d7b2182
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-06/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "gui"
+version = "0.1.0"
+
diff --git a/src/doc/book/listings/ch17-oop/listing-17-06/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-06/Cargo.toml
new file mode 100644
index 000000000..9b816e766
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-06/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "gui"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/src/doc/book/listings/ch17-oop/listing-17-06/src/lib.rs b/src/doc/book/listings/ch17-oop/listing-17-06/src/lib.rs
new file mode 100644
index 000000000..63a8907d3
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-06/src/lib.rs
@@ -0,0 +1,20 @@
+pub trait Draw {
+ fn draw(&self);
+}
+
+// ANCHOR: here
+pub struct Screen<T: Draw> {
+ pub components: Vec<T>,
+}
+
+impl<T> Screen<T>
+where
+ T: Draw,
+{
+ pub fn run(&self) {
+ for component in self.components.iter() {
+ component.draw();
+ }
+ }
+}
+// ANCHOR_END: here
diff --git a/src/doc/book/listings/ch17-oop/listing-17-07/Cargo.lock b/src/doc/book/listings/ch17-oop/listing-17-07/Cargo.lock
new file mode 100644
index 000000000..00d7b2182
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-07/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "gui"
+version = "0.1.0"
+
diff --git a/src/doc/book/listings/ch17-oop/listing-17-07/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-07/Cargo.toml
new file mode 100644
index 000000000..9b816e766
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-07/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "gui"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/src/doc/book/listings/ch17-oop/listing-17-07/src/lib.rs b/src/doc/book/listings/ch17-oop/listing-17-07/src/lib.rs
new file mode 100644
index 000000000..b16cd0155
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-07/src/lib.rs
@@ -0,0 +1,29 @@
+pub trait Draw {
+ fn draw(&self);
+}
+
+pub struct Screen {
+ pub components: Vec<Box<dyn Draw>>,
+}
+
+impl Screen {
+ pub fn run(&self) {
+ for component in self.components.iter() {
+ component.draw();
+ }
+ }
+}
+
+// ANCHOR: here
+pub struct Button {
+ pub width: u32,
+ pub height: u32,
+ pub label: String,
+}
+
+impl Draw for Button {
+ fn draw(&self) {
+ // code to actually draw a button
+ }
+}
+// ANCHOR_END: here
diff --git a/src/doc/book/listings/ch17-oop/listing-17-08/Cargo.lock b/src/doc/book/listings/ch17-oop/listing-17-08/Cargo.lock
new file mode 100644
index 000000000..00d7b2182
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-08/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "gui"
+version = "0.1.0"
+
diff --git a/src/doc/book/listings/ch17-oop/listing-17-08/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-08/Cargo.toml
new file mode 100644
index 000000000..9b816e766
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-08/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "gui"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/src/doc/book/listings/ch17-oop/listing-17-08/src/lib.rs b/src/doc/book/listings/ch17-oop/listing-17-08/src/lib.rs
new file mode 100644
index 000000000..960fee23d
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-08/src/lib.rs
@@ -0,0 +1,27 @@
+pub trait Draw {
+ fn draw(&self);
+}
+
+pub struct Screen {
+ pub components: Vec<Box<dyn Draw>>,
+}
+
+impl Screen {
+ pub fn run(&self) {
+ for component in self.components.iter() {
+ component.draw();
+ }
+ }
+}
+
+pub struct Button {
+ pub width: u32,
+ pub height: u32,
+ pub label: String,
+}
+
+impl Draw for Button {
+ fn draw(&self) {
+ // code to actually draw a button
+ }
+}
diff --git a/src/doc/book/listings/ch17-oop/listing-17-08/src/main.rs b/src/doc/book/listings/ch17-oop/listing-17-08/src/main.rs
new file mode 100644
index 000000000..9575d407e
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-08/src/main.rs
@@ -0,0 +1,17 @@
+// ANCHOR: here
+use gui::Draw;
+
+struct SelectBox {
+ width: u32,
+ height: u32,
+ options: Vec<String>,
+}
+
+impl Draw for SelectBox {
+ fn draw(&self) {
+ // code to actually draw a select box
+ }
+}
+// ANCHOR_END: here
+
+fn main() {}
diff --git a/src/doc/book/listings/ch17-oop/listing-17-09/Cargo.lock b/src/doc/book/listings/ch17-oop/listing-17-09/Cargo.lock
new file mode 100644
index 000000000..00d7b2182
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-09/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "gui"
+version = "0.1.0"
+
diff --git a/src/doc/book/listings/ch17-oop/listing-17-09/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-09/Cargo.toml
new file mode 100644
index 000000000..9b816e766
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-09/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "gui"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/src/doc/book/listings/ch17-oop/listing-17-09/src/lib.rs b/src/doc/book/listings/ch17-oop/listing-17-09/src/lib.rs
new file mode 100644
index 000000000..960fee23d
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-09/src/lib.rs
@@ -0,0 +1,27 @@
+pub trait Draw {
+ fn draw(&self);
+}
+
+pub struct Screen {
+ pub components: Vec<Box<dyn Draw>>,
+}
+
+impl Screen {
+ pub fn run(&self) {
+ for component in self.components.iter() {
+ component.draw();
+ }
+ }
+}
+
+pub struct Button {
+ pub width: u32,
+ pub height: u32,
+ pub label: String,
+}
+
+impl Draw for Button {
+ fn draw(&self) {
+ // code to actually draw a button
+ }
+}
diff --git a/src/doc/book/listings/ch17-oop/listing-17-09/src/main.rs b/src/doc/book/listings/ch17-oop/listing-17-09/src/main.rs
new file mode 100644
index 000000000..4eb13f6b7
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-09/src/main.rs
@@ -0,0 +1,40 @@
+use gui::Draw;
+
+struct SelectBox {
+ width: u32,
+ height: u32,
+ options: Vec<String>,
+}
+
+impl Draw for SelectBox {
+ fn draw(&self) {
+ // code to actually draw a select box
+ }
+}
+
+// ANCHOR: here
+use gui::{Button, Screen};
+
+fn main() {
+ let screen = Screen {
+ components: vec![
+ Box::new(SelectBox {
+ width: 75,
+ height: 10,
+ options: vec![
+ String::from("Yes"),
+ String::from("Maybe"),
+ String::from("No"),
+ ],
+ }),
+ Box::new(Button {
+ width: 50,
+ height: 10,
+ label: String::from("OK"),
+ }),
+ ],
+ };
+
+ screen.run();
+}
+// ANCHOR_END: here
diff --git a/src/doc/book/listings/ch17-oop/listing-17-10/Cargo.lock b/src/doc/book/listings/ch17-oop/listing-17-10/Cargo.lock
new file mode 100644
index 000000000..00d7b2182
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-10/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "gui"
+version = "0.1.0"
+
diff --git a/src/doc/book/listings/ch17-oop/listing-17-10/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-10/Cargo.toml
new file mode 100644
index 000000000..9b816e766
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-10/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "gui"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/src/doc/book/listings/ch17-oop/listing-17-10/output.txt b/src/doc/book/listings/ch17-oop/listing-17-10/output.txt
new file mode 100644
index 000000000..74330fa0a
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-10/output.txt
@@ -0,0 +1,13 @@
+$ cargo run
+ Compiling gui v0.1.0 (file:///projects/gui)
+error[E0277]: the trait bound `String: Draw` is not satisfied
+ --> src/main.rs:5:26
+ |
+5 | components: vec![Box::new(String::from("Hi"))],
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Draw` is not implemented for `String`
+ |
+ = help: the trait `Draw` is implemented for `Button`
+ = note: required for the cast to the object type `dyn Draw`
+
+For more information about this error, try `rustc --explain E0277`.
+error: could not compile `gui` due to previous error
diff --git a/src/doc/book/listings/ch17-oop/listing-17-10/src/lib.rs b/src/doc/book/listings/ch17-oop/listing-17-10/src/lib.rs
new file mode 100644
index 000000000..960fee23d
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-10/src/lib.rs
@@ -0,0 +1,27 @@
+pub trait Draw {
+ fn draw(&self);
+}
+
+pub struct Screen {
+ pub components: Vec<Box<dyn Draw>>,
+}
+
+impl Screen {
+ pub fn run(&self) {
+ for component in self.components.iter() {
+ component.draw();
+ }
+ }
+}
+
+pub struct Button {
+ pub width: u32,
+ pub height: u32,
+ pub label: String,
+}
+
+impl Draw for Button {
+ fn draw(&self) {
+ // code to actually draw a button
+ }
+}
diff --git a/src/doc/book/listings/ch17-oop/listing-17-10/src/main.rs b/src/doc/book/listings/ch17-oop/listing-17-10/src/main.rs
new file mode 100644
index 000000000..2ede87ab7
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-10/src/main.rs
@@ -0,0 +1,9 @@
+use gui::Screen;
+
+fn main() {
+ let screen = Screen {
+ components: vec![Box::new(String::from("Hi"))],
+ };
+
+ screen.run();
+}
diff --git a/src/doc/book/listings/ch17-oop/listing-17-11/Cargo.lock b/src/doc/book/listings/ch17-oop/listing-17-11/Cargo.lock
new file mode 100644
index 000000000..b6f4232c6
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-11/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "blog"
+version = "0.1.0"
+
diff --git a/src/doc/book/listings/ch17-oop/listing-17-11/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-11/Cargo.toml
new file mode 100644
index 000000000..1619af5c6
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-11/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "blog"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/src/doc/book/listings/ch17-oop/listing-17-11/src/main.rs b/src/doc/book/listings/ch17-oop/listing-17-11/src/main.rs
new file mode 100644
index 000000000..d99170a97
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-11/src/main.rs
@@ -0,0 +1,20 @@
+// ANCHOR: all
+use blog::Post;
+
+// ANCHOR: here
+fn main() {
+ let mut post = Post::new();
+
+ post.add_text("I ate a salad for lunch today");
+ assert_eq!("", post.content());
+ // ANCHOR_END: here
+
+ post.request_review();
+ assert_eq!("", post.content());
+
+ post.approve();
+ assert_eq!("I ate a salad for lunch today", post.content());
+ // ANCHOR: here
+}
+// ANCHOR_END: here
+// ANCHOR_END: all
diff --git a/src/doc/book/listings/ch17-oop/listing-17-12/Cargo.lock b/src/doc/book/listings/ch17-oop/listing-17-12/Cargo.lock
new file mode 100644
index 000000000..b6f4232c6
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-12/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "blog"
+version = "0.1.0"
+
diff --git a/src/doc/book/listings/ch17-oop/listing-17-12/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-12/Cargo.toml
new file mode 100644
index 000000000..1619af5c6
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-12/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "blog"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/src/doc/book/listings/ch17-oop/listing-17-12/src/lib.rs b/src/doc/book/listings/ch17-oop/listing-17-12/src/lib.rs
new file mode 100644
index 000000000..b8156c39d
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-12/src/lib.rs
@@ -0,0 +1,19 @@
+pub struct Post {
+ state: Option<Box<dyn State>>,
+ content: String,
+}
+
+impl Post {
+ pub fn new() -> Post {
+ Post {
+ state: Some(Box::new(Draft {})),
+ content: String::new(),
+ }
+ }
+}
+
+trait State {}
+
+struct Draft {}
+
+impl State for Draft {}
diff --git a/src/doc/book/listings/ch17-oop/listing-17-12/src/main.rs b/src/doc/book/listings/ch17-oop/listing-17-12/src/main.rs
new file mode 100644
index 000000000..14b4c0824
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-12/src/main.rs
@@ -0,0 +1,14 @@
+use blog::Post;
+
+fn main() {
+ let mut post = Post::new();
+
+ post.add_text("I ate a salad for lunch today");
+ assert_eq!("", post.content());
+
+ post.request_review();
+ assert_eq!("", post.content());
+
+ post.approve();
+ assert_eq!("I ate a salad for lunch today", post.content());
+}
diff --git a/src/doc/book/listings/ch17-oop/listing-17-13/Cargo.lock b/src/doc/book/listings/ch17-oop/listing-17-13/Cargo.lock
new file mode 100644
index 000000000..b6f4232c6
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-13/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "blog"
+version = "0.1.0"
+
diff --git a/src/doc/book/listings/ch17-oop/listing-17-13/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-13/Cargo.toml
new file mode 100644
index 000000000..1619af5c6
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-13/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "blog"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/src/doc/book/listings/ch17-oop/listing-17-13/src/lib.rs b/src/doc/book/listings/ch17-oop/listing-17-13/src/lib.rs
new file mode 100644
index 000000000..bd68557a0
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-13/src/lib.rs
@@ -0,0 +1,28 @@
+pub struct Post {
+ state: Option<Box<dyn State>>,
+ content: String,
+}
+
+// ANCHOR: here
+impl Post {
+ // --snip--
+ // ANCHOR_END: here
+ pub fn new() -> Post {
+ Post {
+ state: Some(Box::new(Draft {})),
+ content: String::new(),
+ }
+ }
+
+ // ANCHOR: here
+ pub fn add_text(&mut self, text: &str) {
+ self.content.push_str(text);
+ }
+}
+// ANCHOR_END: here
+
+trait State {}
+
+struct Draft {}
+
+impl State for Draft {}
diff --git a/src/doc/book/listings/ch17-oop/listing-17-13/src/main.rs b/src/doc/book/listings/ch17-oop/listing-17-13/src/main.rs
new file mode 100644
index 000000000..14b4c0824
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-13/src/main.rs
@@ -0,0 +1,14 @@
+use blog::Post;
+
+fn main() {
+ let mut post = Post::new();
+
+ post.add_text("I ate a salad for lunch today");
+ assert_eq!("", post.content());
+
+ post.request_review();
+ assert_eq!("", post.content());
+
+ post.approve();
+ assert_eq!("I ate a salad for lunch today", post.content());
+}
diff --git a/src/doc/book/listings/ch17-oop/listing-17-14/Cargo.lock b/src/doc/book/listings/ch17-oop/listing-17-14/Cargo.lock
new file mode 100644
index 000000000..b6f4232c6
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-14/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "blog"
+version = "0.1.0"
+
diff --git a/src/doc/book/listings/ch17-oop/listing-17-14/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-14/Cargo.toml
new file mode 100644
index 000000000..1619af5c6
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-14/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "blog"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/src/doc/book/listings/ch17-oop/listing-17-14/src/lib.rs b/src/doc/book/listings/ch17-oop/listing-17-14/src/lib.rs
new file mode 100644
index 000000000..09cf0c466
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-14/src/lib.rs
@@ -0,0 +1,32 @@
+pub struct Post {
+ state: Option<Box<dyn State>>,
+ content: String,
+}
+
+// ANCHOR: here
+impl Post {
+ // --snip--
+ // ANCHOR_END: here
+ pub fn new() -> Post {
+ Post {
+ state: Some(Box::new(Draft {})),
+ content: String::new(),
+ }
+ }
+
+ pub fn add_text(&mut self, text: &str) {
+ self.content.push_str(text);
+ }
+
+ // ANCHOR: here
+ pub fn content(&self) -> &str {
+ ""
+ }
+}
+// ANCHOR_END: here
+
+trait State {}
+
+struct Draft {}
+
+impl State for Draft {}
diff --git a/src/doc/book/listings/ch17-oop/listing-17-14/src/main.rs b/src/doc/book/listings/ch17-oop/listing-17-14/src/main.rs
new file mode 100644
index 000000000..14b4c0824
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-14/src/main.rs
@@ -0,0 +1,14 @@
+use blog::Post;
+
+fn main() {
+ let mut post = Post::new();
+
+ post.add_text("I ate a salad for lunch today");
+ assert_eq!("", post.content());
+
+ post.request_review();
+ assert_eq!("", post.content());
+
+ post.approve();
+ assert_eq!("I ate a salad for lunch today", post.content());
+}
diff --git a/src/doc/book/listings/ch17-oop/listing-17-15/Cargo.lock b/src/doc/book/listings/ch17-oop/listing-17-15/Cargo.lock
new file mode 100644
index 000000000..b6f4232c6
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-15/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "blog"
+version = "0.1.0"
+
diff --git a/src/doc/book/listings/ch17-oop/listing-17-15/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-15/Cargo.toml
new file mode 100644
index 000000000..1619af5c6
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-15/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "blog"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/src/doc/book/listings/ch17-oop/listing-17-15/src/lib.rs b/src/doc/book/listings/ch17-oop/listing-17-15/src/lib.rs
new file mode 100644
index 000000000..909dd5274
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-15/src/lib.rs
@@ -0,0 +1,52 @@
+pub struct Post {
+ state: Option<Box<dyn State>>,
+ content: String,
+}
+
+// ANCHOR: here
+impl Post {
+ // --snip--
+ // ANCHOR_END: here
+ pub fn new() -> Post {
+ Post {
+ state: Some(Box::new(Draft {})),
+ content: String::new(),
+ }
+ }
+
+ pub fn add_text(&mut self, text: &str) {
+ self.content.push_str(text);
+ }
+
+ pub fn content(&self) -> &str {
+ ""
+ }
+
+ // ANCHOR: here
+ pub fn request_review(&mut self) {
+ if let Some(s) = self.state.take() {
+ self.state = Some(s.request_review())
+ }
+ }
+}
+
+trait State {
+ fn request_review(self: Box<Self>) -> Box<dyn State>;
+}
+
+struct Draft {}
+
+impl State for Draft {
+ fn request_review(self: Box<Self>) -> Box<dyn State> {
+ Box::new(PendingReview {})
+ }
+}
+
+struct PendingReview {}
+
+impl State for PendingReview {
+ fn request_review(self: Box<Self>) -> Box<dyn State> {
+ self
+ }
+}
+// ANCHOR_END: here
diff --git a/src/doc/book/listings/ch17-oop/listing-17-15/src/main.rs b/src/doc/book/listings/ch17-oop/listing-17-15/src/main.rs
new file mode 100644
index 000000000..14b4c0824
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-15/src/main.rs
@@ -0,0 +1,14 @@
+use blog::Post;
+
+fn main() {
+ let mut post = Post::new();
+
+ post.add_text("I ate a salad for lunch today");
+ assert_eq!("", post.content());
+
+ post.request_review();
+ assert_eq!("", post.content());
+
+ post.approve();
+ assert_eq!("I ate a salad for lunch today", post.content());
+}
diff --git a/src/doc/book/listings/ch17-oop/listing-17-16/Cargo.lock b/src/doc/book/listings/ch17-oop/listing-17-16/Cargo.lock
new file mode 100644
index 000000000..b6f4232c6
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-16/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "blog"
+version = "0.1.0"
+
diff --git a/src/doc/book/listings/ch17-oop/listing-17-16/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-16/Cargo.toml
new file mode 100644
index 000000000..1619af5c6
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-16/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "blog"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/src/doc/book/listings/ch17-oop/listing-17-16/src/lib.rs b/src/doc/book/listings/ch17-oop/listing-17-16/src/lib.rs
new file mode 100644
index 000000000..92cb29813
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-16/src/lib.rs
@@ -0,0 +1,85 @@
+pub struct Post {
+ state: Option<Box<dyn State>>,
+ content: String,
+}
+
+// ANCHOR: here
+impl Post {
+ // --snip--
+ // ANCHOR_END: here
+ pub fn new() -> Post {
+ Post {
+ state: Some(Box::new(Draft {})),
+ content: String::new(),
+ }
+ }
+
+ pub fn add_text(&mut self, text: &str) {
+ self.content.push_str(text);
+ }
+
+ pub fn content(&self) -> &str {
+ ""
+ }
+
+ pub fn request_review(&mut self) {
+ if let Some(s) = self.state.take() {
+ self.state = Some(s.request_review())
+ }
+ }
+
+ // ANCHOR: here
+ pub fn approve(&mut self) {
+ if let Some(s) = self.state.take() {
+ self.state = Some(s.approve())
+ }
+ }
+}
+
+trait State {
+ fn request_review(self: Box<Self>) -> Box<dyn State>;
+ fn approve(self: Box<Self>) -> Box<dyn State>;
+}
+
+struct Draft {}
+
+impl State for Draft {
+ // --snip--
+ // ANCHOR_END: here
+ fn request_review(self: Box<Self>) -> Box<dyn State> {
+ Box::new(PendingReview {})
+ }
+
+ // ANCHOR: here
+ fn approve(self: Box<Self>) -> Box<dyn State> {
+ self
+ }
+}
+
+struct PendingReview {}
+
+impl State for PendingReview {
+ // --snip--
+ // ANCHOR_END: here
+ fn request_review(self: Box<Self>) -> Box<dyn State> {
+ self
+ }
+
+ // ANCHOR: here
+ fn approve(self: Box<Self>) -> Box<dyn State> {
+ Box::new(Published {})
+ }
+}
+
+struct Published {}
+
+impl State for Published {
+ fn request_review(self: Box<Self>) -> Box<dyn State> {
+ self
+ }
+
+ fn approve(self: Box<Self>) -> Box<dyn State> {
+ self
+ }
+}
+// ANCHOR_END: here
diff --git a/src/doc/book/listings/ch17-oop/listing-17-16/src/main.rs b/src/doc/book/listings/ch17-oop/listing-17-16/src/main.rs
new file mode 100644
index 000000000..14b4c0824
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-16/src/main.rs
@@ -0,0 +1,14 @@
+use blog::Post;
+
+fn main() {
+ let mut post = Post::new();
+
+ post.add_text("I ate a salad for lunch today");
+ assert_eq!("", post.content());
+
+ post.request_review();
+ assert_eq!("", post.content());
+
+ post.approve();
+ assert_eq!("I ate a salad for lunch today", post.content());
+}
diff --git a/src/doc/book/listings/ch17-oop/listing-17-17/Cargo.lock b/src/doc/book/listings/ch17-oop/listing-17-17/Cargo.lock
new file mode 100644
index 000000000..b6f4232c6
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-17/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "blog"
+version = "0.1.0"
+
diff --git a/src/doc/book/listings/ch17-oop/listing-17-17/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-17/Cargo.toml
new file mode 100644
index 000000000..1619af5c6
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-17/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "blog"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/src/doc/book/listings/ch17-oop/listing-17-17/src/lib.rs b/src/doc/book/listings/ch17-oop/listing-17-17/src/lib.rs
new file mode 100644
index 000000000..0beee7b8d
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-17/src/lib.rs
@@ -0,0 +1,82 @@
+pub struct Post {
+ state: Option<Box<dyn State>>,
+ content: String,
+}
+
+// ANCHOR: here
+impl Post {
+ // --snip--
+ // ANCHOR_END: here
+ pub fn new() -> Post {
+ Post {
+ state: Some(Box::new(Draft {})),
+ content: String::new(),
+ }
+ }
+
+ pub fn add_text(&mut self, text: &str) {
+ self.content.push_str(text);
+ }
+
+ // ANCHOR: here
+ pub fn content(&self) -> &str {
+ self.state.as_ref().unwrap().content(self)
+ }
+ // --snip--
+ // ANCHOR_END: here
+
+ pub fn request_review(&mut self) {
+ if let Some(s) = self.state.take() {
+ self.state = Some(s.request_review())
+ }
+ }
+
+ pub fn approve(&mut self) {
+ if let Some(s) = self.state.take() {
+ self.state = Some(s.approve())
+ }
+ }
+ // ANCHOR: here
+}
+// ANCHOR_END: here
+
+trait State {
+ fn request_review(self: Box<Self>) -> Box<dyn State>;
+ fn approve(self: Box<Self>) -> Box<dyn State>;
+}
+
+struct Draft {}
+
+impl State for Draft {
+ fn request_review(self: Box<Self>) -> Box<dyn State> {
+ Box::new(PendingReview {})
+ }
+
+ fn approve(self: Box<Self>) -> Box<dyn State> {
+ self
+ }
+}
+
+struct PendingReview {}
+
+impl State for PendingReview {
+ fn request_review(self: Box<Self>) -> Box<dyn State> {
+ self
+ }
+
+ fn approve(self: Box<Self>) -> Box<dyn State> {
+ Box::new(Published {})
+ }
+}
+
+struct Published {}
+
+impl State for Published {
+ fn request_review(self: Box<Self>) -> Box<dyn State> {
+ self
+ }
+
+ fn approve(self: Box<Self>) -> Box<dyn State> {
+ self
+ }
+}
diff --git a/src/doc/book/listings/ch17-oop/listing-17-17/src/main.rs b/src/doc/book/listings/ch17-oop/listing-17-17/src/main.rs
new file mode 100644
index 000000000..14b4c0824
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-17/src/main.rs
@@ -0,0 +1,14 @@
+use blog::Post;
+
+fn main() {
+ let mut post = Post::new();
+
+ post.add_text("I ate a salad for lunch today");
+ assert_eq!("", post.content());
+
+ post.request_review();
+ assert_eq!("", post.content());
+
+ post.approve();
+ assert_eq!("I ate a salad for lunch today", post.content());
+}
diff --git a/src/doc/book/listings/ch17-oop/listing-17-18/Cargo.lock b/src/doc/book/listings/ch17-oop/listing-17-18/Cargo.lock
new file mode 100644
index 000000000..b6f4232c6
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-18/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "blog"
+version = "0.1.0"
+
diff --git a/src/doc/book/listings/ch17-oop/listing-17-18/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-18/Cargo.toml
new file mode 100644
index 000000000..1619af5c6
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-18/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "blog"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/src/doc/book/listings/ch17-oop/listing-17-18/src/lib.rs b/src/doc/book/listings/ch17-oop/listing-17-18/src/lib.rs
new file mode 100644
index 000000000..1bac8a87a
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-18/src/lib.rs
@@ -0,0 +1,94 @@
+pub struct Post {
+ state: Option<Box<dyn State>>,
+ content: String,
+}
+
+impl Post {
+ pub fn new() -> Post {
+ Post {
+ state: Some(Box::new(Draft {})),
+ content: String::new(),
+ }
+ }
+
+ pub fn add_text(&mut self, text: &str) {
+ self.content.push_str(text);
+ }
+
+ pub fn content(&self) -> &str {
+ self.state.as_ref().unwrap().content(self)
+ }
+
+ pub fn request_review(&mut self) {
+ if let Some(s) = self.state.take() {
+ self.state = Some(s.request_review())
+ }
+ }
+
+ pub fn approve(&mut self) {
+ if let Some(s) = self.state.take() {
+ self.state = Some(s.approve())
+ }
+ }
+}
+
+// ANCHOR: here
+trait State {
+ // --snip--
+ // ANCHOR_END: here
+ fn request_review(self: Box<Self>) -> Box<dyn State>;
+ fn approve(self: Box<Self>) -> Box<dyn State>;
+
+ // ANCHOR: here
+ fn content<'a>(&self, post: &'a Post) -> &'a str {
+ ""
+ }
+}
+
+// --snip--
+// ANCHOR_END: here
+
+struct Draft {}
+
+impl State for Draft {
+ fn request_review(self: Box<Self>) -> Box<dyn State> {
+ Box::new(PendingReview {})
+ }
+
+ fn approve(self: Box<Self>) -> Box<dyn State> {
+ self
+ }
+}
+
+struct PendingReview {}
+
+impl State for PendingReview {
+ fn request_review(self: Box<Self>) -> Box<dyn State> {
+ self
+ }
+
+ fn approve(self: Box<Self>) -> Box<dyn State> {
+ Box::new(Published {})
+ }
+}
+
+// ANCHOR: here
+struct Published {}
+
+impl State for Published {
+ // --snip--
+ // ANCHOR_END: here
+ fn request_review(self: Box<Self>) -> Box<dyn State> {
+ self
+ }
+
+ fn approve(self: Box<Self>) -> Box<dyn State> {
+ self
+ }
+
+ // ANCHOR: here
+ fn content<'a>(&self, post: &'a Post) -> &'a str {
+ &post.content
+ }
+}
+// ANCHOR_END: here
diff --git a/src/doc/book/listings/ch17-oop/listing-17-18/src/main.rs b/src/doc/book/listings/ch17-oop/listing-17-18/src/main.rs
new file mode 100644
index 000000000..14b4c0824
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-18/src/main.rs
@@ -0,0 +1,14 @@
+use blog::Post;
+
+fn main() {
+ let mut post = Post::new();
+
+ post.add_text("I ate a salad for lunch today");
+ assert_eq!("", post.content());
+
+ post.request_review();
+ assert_eq!("", post.content());
+
+ post.approve();
+ assert_eq!("I ate a salad for lunch today", post.content());
+}
diff --git a/src/doc/book/listings/ch17-oop/listing-17-19/Cargo.lock b/src/doc/book/listings/ch17-oop/listing-17-19/Cargo.lock
new file mode 100644
index 000000000..b6f4232c6
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-19/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "blog"
+version = "0.1.0"
+
diff --git a/src/doc/book/listings/ch17-oop/listing-17-19/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-19/Cargo.toml
new file mode 100644
index 000000000..1619af5c6
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-19/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "blog"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/src/doc/book/listings/ch17-oop/listing-17-19/src/lib.rs b/src/doc/book/listings/ch17-oop/listing-17-19/src/lib.rs
new file mode 100644
index 000000000..bfe034eaf
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-19/src/lib.rs
@@ -0,0 +1,25 @@
+pub struct Post {
+ content: String,
+}
+
+pub struct DraftPost {
+ content: String,
+}
+
+impl Post {
+ pub fn new() -> DraftPost {
+ DraftPost {
+ content: String::new(),
+ }
+ }
+
+ pub fn content(&self) -> &str {
+ &self.content
+ }
+}
+
+impl DraftPost {
+ pub fn add_text(&mut self, text: &str) {
+ self.content.push_str(text);
+ }
+}
diff --git a/src/doc/book/listings/ch17-oop/listing-17-20/Cargo.lock b/src/doc/book/listings/ch17-oop/listing-17-20/Cargo.lock
new file mode 100644
index 000000000..b6f4232c6
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-20/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "blog"
+version = "0.1.0"
+
diff --git a/src/doc/book/listings/ch17-oop/listing-17-20/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-20/Cargo.toml
new file mode 100644
index 000000000..1619af5c6
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-20/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "blog"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/src/doc/book/listings/ch17-oop/listing-17-20/src/lib.rs b/src/doc/book/listings/ch17-oop/listing-17-20/src/lib.rs
new file mode 100644
index 000000000..3b82ec05d
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-20/src/lib.rs
@@ -0,0 +1,48 @@
+pub struct Post {
+ content: String,
+}
+
+pub struct DraftPost {
+ content: String,
+}
+
+impl Post {
+ pub fn new() -> DraftPost {
+ DraftPost {
+ content: String::new(),
+ }
+ }
+
+ pub fn content(&self) -> &str {
+ &self.content
+ }
+}
+
+// ANCHOR: here
+impl DraftPost {
+ // --snip--
+ // ANCHOR_END: here
+ pub fn add_text(&mut self, text: &str) {
+ self.content.push_str(text);
+ }
+
+ // ANCHOR: here
+ pub fn request_review(self) -> PendingReviewPost {
+ PendingReviewPost {
+ content: self.content,
+ }
+ }
+}
+
+pub struct PendingReviewPost {
+ content: String,
+}
+
+impl PendingReviewPost {
+ pub fn approve(self) -> Post {
+ Post {
+ content: self.content,
+ }
+ }
+}
+// ANCHOR_END: here
diff --git a/src/doc/book/listings/ch17-oop/listing-17-21/Cargo.lock b/src/doc/book/listings/ch17-oop/listing-17-21/Cargo.lock
new file mode 100644
index 000000000..b6f4232c6
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-21/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "blog"
+version = "0.1.0"
+
diff --git a/src/doc/book/listings/ch17-oop/listing-17-21/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-21/Cargo.toml
new file mode 100644
index 000000000..1619af5c6
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-21/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "blog"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/src/doc/book/listings/ch17-oop/listing-17-21/src/lib.rs b/src/doc/book/listings/ch17-oop/listing-17-21/src/lib.rs
new file mode 100644
index 000000000..38500a651
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-21/src/lib.rs
@@ -0,0 +1,43 @@
+pub struct Post {
+ content: String,
+}
+
+pub struct DraftPost {
+ content: String,
+}
+
+impl Post {
+ pub fn new() -> DraftPost {
+ DraftPost {
+ content: String::new(),
+ }
+ }
+
+ pub fn content(&self) -> &str {
+ &self.content
+ }
+}
+
+impl DraftPost {
+ pub fn add_text(&mut self, text: &str) {
+ self.content.push_str(text);
+ }
+
+ pub fn request_review(self) -> PendingReviewPost {
+ PendingReviewPost {
+ content: self.content,
+ }
+ }
+}
+
+pub struct PendingReviewPost {
+ content: String,
+}
+
+impl PendingReviewPost {
+ pub fn approve(self) -> Post {
+ Post {
+ content: self.content,
+ }
+ }
+}
diff --git a/src/doc/book/listings/ch17-oop/listing-17-21/src/main.rs b/src/doc/book/listings/ch17-oop/listing-17-21/src/main.rs
new file mode 100644
index 000000000..720c55e6a
--- /dev/null
+++ b/src/doc/book/listings/ch17-oop/listing-17-21/src/main.rs
@@ -0,0 +1,13 @@
+use blog::Post;
+
+fn main() {
+ let mut post = Post::new();
+
+ post.add_text("I ate a salad for lunch today");
+
+ let post = post.request_review();
+
+ let post = post.approve();
+
+ assert_eq!("I ate a salad for lunch today", post.content());
+}