Skip to content

Commit cba5901

Browse files
committed
enum.
1 parent 1efe9c5 commit cba5901

File tree

7 files changed

+245
-1
lines changed

7 files changed

+245
-1
lines changed

Cargo.lock

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ members = [
1010
"chapter8/*",
1111
"chapter9/*",
1212
"chapter11/*"
13-
, "chapter12", "chapter13", "chapter7/errors"]
13+
, "chapter12", "chapter13", "chapter7/errors", "chapter10"]
1414
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

chapter10/Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[package]
2+
name = "chapter10"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]

chapter10/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# 列挙型とパターン
2+
3+
## 列挙型
4+
5+
* データを保持する列挙型
6+
* 列挙型のメモリ上での表現
7+
* 列挙型を用いたリッチなデータ構造
8+
* ジェネリクスと列挙型
9+
10+
## パターン
11+
12+
* パターンマッチング

chapter10/src/btree.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
use std::fmt::Display;
2+
3+
#[derive(PartialEq, Eq)]
4+
pub enum BinaryTree<T> {
5+
Empty,
6+
NonEmpty(Box<TreeNode<T>>),
7+
}
8+
impl<T: Display + PartialEq + Eq> Display for BinaryTree<T> {
9+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
10+
match *self {
11+
BinaryTree::Empty => write!(f, "()"),
12+
BinaryTree::NonEmpty(ref node) => write!(f, "{}", node.element),
13+
}
14+
}
15+
}
16+
17+
#[derive(PartialEq, Eq)]
18+
pub struct TreeNode<T> {
19+
element: T,
20+
left: BinaryTree<T>,
21+
right: BinaryTree<T>,
22+
}
23+
24+
#[cfg(test)]
25+
mod test {
26+
use super::*;
27+
28+
#[test]
29+
fn test_build_btree_left_and_right_5depth_element_string() {
30+
let tree = BinaryTree::NonEmpty(Box::new(TreeNode {
31+
element: "A",
32+
left: BinaryTree::NonEmpty(Box::new(TreeNode {
33+
element: "B",
34+
left: BinaryTree::NonEmpty(Box::new(TreeNode {
35+
element: "D",
36+
left: BinaryTree::Empty,
37+
right: BinaryTree::Empty,
38+
})),
39+
right: BinaryTree::NonEmpty(Box::new(TreeNode {
40+
element: "E",
41+
left: BinaryTree::Empty,
42+
right: BinaryTree::Empty,
43+
})),
44+
})),
45+
right: BinaryTree::NonEmpty(Box::new(TreeNode {
46+
element: "C",
47+
left: BinaryTree::Empty,
48+
right: BinaryTree::NonEmpty(Box::new(TreeNode {
49+
element: "F",
50+
left: BinaryTree::Empty,
51+
right: BinaryTree::Empty,
52+
})),
53+
})),
54+
}));
55+
56+
match tree {
57+
BinaryTree::Empty => assert!(BinaryTree::<&str>::Empty == BinaryTree::Empty),
58+
BinaryTree::NonEmpty(ref t) => {
59+
assert_eq!(t.element, "A")
60+
}
61+
}
62+
}
63+
}

chapter10/src/lib.rs

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
mod btree;
2+
3+
/// HTTPステータスコードを表す列挙型
4+
pub enum HttpStatus {
5+
Ok = 200,
6+
NotModified = 304,
7+
NotFound = 404,
8+
}
9+
10+
/// 時間単位を表す列挙型
11+
#[derive(Debug, Clone, Copy, PartialEq)]
12+
pub enum TimeUnit {
13+
Seconds,
14+
Minutes,
15+
Hours,
16+
Days,
17+
Months,
18+
Years,
19+
}
20+
21+
/// 単位に関するメソッドを提供する
22+
impl TimeUnit {
23+
pub fn plural(self) -> &'static str {
24+
match self {
25+
Self::Seconds => "seconds",
26+
Self::Minutes => "minutes",
27+
Self::Hours => "hours",
28+
Self::Days => "days",
29+
Self::Months => "months",
30+
Self::Years => "years",
31+
}
32+
}
33+
pub fn singular(self) -> &'static str {
34+
self.plural().trim_end_matches('s')
35+
}
36+
}
37+
38+
/// 粗い時間を表す列挙型
39+
#[derive(Debug, PartialEq, Clone, Copy)]
40+
pub enum RoughTime {
41+
InThePast(TimeUnit, u32),
42+
JustNow,
43+
InTheFuture(TimeUnit, u32),
44+
}
45+
46+
pub struct Point3d {
47+
x: f32,
48+
y: f32,
49+
z: f32,
50+
}
51+
/// 構造体型列挙型
52+
pub enum Shape {
53+
Sphere { center: Point3d, radius: f32 },
54+
Cuboid { corner1: Point3d, corner2: Point3d },
55+
}
56+
57+
impl Shape {
58+
pub fn volume(&self) -> f32 {
59+
match self {
60+
Self::Sphere { radius, .. } => 4.0 / 3.0 * std::f32::consts::PI * radius.powi(3),
61+
Self::Cuboid { corner1, corner2 } => {
62+
let diff = Point3d {
63+
x: (corner1.x - corner2.x).abs(),
64+
y: (corner1.y - corner2.y).abs(),
65+
z: (corner1.z - corner2.z).abs(),
66+
};
67+
diff.x * diff.y * diff.z
68+
}
69+
}
70+
}
71+
}
72+
73+
#[cfg(test)]
74+
mod tests {
75+
use super::*;
76+
use std::mem;
77+
#[test]
78+
fn test_http_status_size_of() {
79+
let size = mem::size_of::<HttpStatus>();
80+
assert_eq!(size, 2);
81+
assert_eq!(mem::size_of::<HttpStatus>(), 2);
82+
assert_eq!(HttpStatus::NotFound as i32, 404);
83+
}
84+
#[test]
85+
fn test_time_unit() {
86+
assert_eq!(TimeUnit::Seconds.plural(), "seconds");
87+
assert_eq!(TimeUnit::Seconds.singular(), "second");
88+
assert_eq!(TimeUnit::Minutes.plural(), "minutes");
89+
assert_eq!(TimeUnit::Minutes.singular(), "minute");
90+
assert_eq!(TimeUnit::Hours.plural(), "hours");
91+
assert_eq!(TimeUnit::Hours.singular(), "hour");
92+
assert_eq!(TimeUnit::Days.plural(), "days");
93+
assert_eq!(TimeUnit::Days.singular(), "day");
94+
assert_eq!(TimeUnit::Months.plural(), "months");
95+
assert_eq!(TimeUnit::Months.singular(), "month");
96+
assert_eq!(TimeUnit::Years.plural(), "years");
97+
assert_eq!(TimeUnit::Years.singular(), "year");
98+
}
99+
100+
#[test]
101+
fn test_rough_time() {
102+
let r = RoughTime::InThePast(TimeUnit::Seconds, 7);
103+
assert_eq!(r, RoughTime::InThePast(TimeUnit::Seconds, 7));
104+
assert_ne!(r, RoughTime::InThePast(TimeUnit::Seconds, 8));
105+
assert_ne!(r, RoughTime::InThePast(TimeUnit::Minutes, 7));
106+
assert_ne!(r, RoughTime::JustNow);
107+
assert_ne!(r, RoughTime::InTheFuture(TimeUnit::Seconds, 7));
108+
}
109+
110+
#[test]
111+
fn test_shape() {
112+
let c = Point3d {
113+
x: 0.0,
114+
y: 0.0,
115+
z: 0.0,
116+
};
117+
let s = Shape::Sphere {
118+
center: c,
119+
radius: 1.0,
120+
};
121+
match s {
122+
Shape::Sphere { center, radius } => {
123+
assert_eq!(center.x, 0.0);
124+
assert_eq!(center.y, 0.0);
125+
assert_eq!(center.z, 0.0);
126+
assert_eq!(radius, 1.0);
127+
}
128+
Shape::Cuboid { .. } => {
129+
panic!("Expected a sphere, got a cuboid!");
130+
}
131+
}
132+
let corner1 = Point3d {
133+
x: 0.0,
134+
y: 0.0,
135+
z: 0.0,
136+
};
137+
let corner2 = Point3d {
138+
x: 1.0,
139+
y: 1.0,
140+
z: 1.0,
141+
};
142+
let c = Shape::Cuboid { corner1, corner2 };
143+
assert_eq!(c.volume(), 1.0);
144+
match c {
145+
Shape::Cuboid { corner1, corner2 } => {
146+
assert_eq!(corner1.x, 0.0);
147+
assert_eq!(corner1.y, 0.0);
148+
assert_eq!(corner1.z, 0.0);
149+
assert_eq!(corner2.x, 1.0);
150+
assert_eq!(corner2.y, 1.0);
151+
assert_eq!(corner2.z, 1.0);
152+
}
153+
Shape::Sphere { .. } => {
154+
panic!("Expected a cuboid, got a sphere!");
155+
}
156+
}
157+
}
158+
}

chapter10/src/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

0 commit comments

Comments
 (0)