Skip to content

Commit

Permalink
error 处理
Browse files Browse the repository at this point in the history
  • Loading branch information
Danny5487401 committed Aug 27, 2024
1 parent 9fefa78 commit 7505665
Show file tree
Hide file tree
Showing 18 changed files with 582 additions and 3 deletions.
3 changes: 3 additions & 0 deletions .idea/advanced_rust.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 35 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@


[workspace]
members = [ "app", "chapter01-log", "chapter02-feature", "chapter03-ownership", "chapter04-lifecycle", "chapter05-memory", "chapter06-type", "chapter07-pointer", "chapter08-vec"]
members = ["app", "chapter01-log",
"chapter02-feature", "chapter03-ownership",
"chapter04-lifecycle", "chapter05-memory", "chapter06-type",
"chapter07-pointer", "chapter08-vec", "chapter09-hash", "chapter10-error", "chapter11-closure"]


[workspace.dependencies]
Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,20 @@
- [2 动态数组 Vector 和 数组 [T; n] 如何转化成 &[T]](chapter08-vec/src/vec2-slice.rs)
- [3 String、&String 转换成 &str](chapter08-vec/src/vec3-string-slice.rs)

## [第九章:hash](chapter09-hash/hashmap.md)

- 1 hashmap cap 扩容和缩容
- 2 HashSet
- 3 BTreeMap

## [第十章:error 错误处理](chapter10-error/error.md)

- [1 使用 ? 进行传播错误](chapter10-error/src/error1-transfer.rs)

## [第十一章:闭包](chapter11-closure/closure.md)

- 1 闭包的大小跟参数、局部变量都无关,只跟捕获的变量有关

## 参考

- [Rust语言圣经](https://github.com/sunface/rust-course)
Expand Down
19 changes: 19 additions & 0 deletions chapter09-hash/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "chapter09-hashmap"
version.workspace = true
edition.workspace = true
authors.workspace = true

[[bin]]
name = "hash1"
path = "src/hash1-cap.rs"


[[bin]]
name = "hash2"
path = "src/hash2-hashset.rs"


[[bin]]
name = "hash3"
path = "src/hash3-btreemap.rs"
99 changes: 99 additions & 0 deletions chapter09-hash/hashmap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# hash

## hashMap

### 结构

```rust
pub struct HashMap<K, V, S = DefaultHashBuilder, A: Allocator = Global> {
pub(crate) hash_builder: S,
pub(crate) table: RawTable<(K, V), A>,
}
```

```rust
pub struct RawTable<T, A: Allocator = Global> {
table: RawTableInner,
alloc: A,
// Tell dropck that we own instances of T.
marker: PhantomData<T>,
}

/// Non-generic part of `RawTable` which allows functions to be instantiated only once regardless
/// of how many different key-value types are used.
struct RawTableInner {
// 哈希表中哈希桶的数量减一
bucket_mask: usize,

// [Padding], T1, T2, ..., Tlast, C1, C2, ...
// ^ points here
// 指向堆内存哈希表末端的 ctrl 区
ctrl: NonNull<u8>,

// Number of elements that can be inserted before we need to grow the table
growth_left: usize,

// Number of elements in the table, only really used by len()
items: usize,
}
```

### 扩容和缩容

当 HashMap::new() 时,它并没有分配空间,容量为零,随着哈希表不断插入数据,它会以 2 的幂减一的方式增长,最小是3。

以 2 的 n 次幂的方式进行扩容,0,3 (22 - 1),7 (23 - 1),14 (24 - 24 * 12.5%),28 (25 - 25 * 12.5%)

```rust
pub struct HashMap<K, V, S = RandomState> {
base: base::HashMap<K, V, S>,
}

impl<K, V, S> HashMap<K, V, S>
where
K: Eq + Hash,
S: BuildHasher,
{
pub fn insert(&mut self, k: K, v: V) -> Option<V> {
self.base.insert(k, v)
}
}
```

```rust
impl<K, V, S, A> HashMap<K, V, S, A>
where
K: Eq + Hash,
S: BuildHasher,
A: Allocator,
{
pub fn insert(&mut self, k: K, v: V) -> Option<V> {
// 哈希,得到一个哈希值 hash
let hash = make_hash::<K, S>(&self.hash_builder, &k);
let hasher = make_hasher::<_, V, S>(&self.hash_builder);
match self
.table
.find_or_find_insert_slot(hash, equivalent_key(&k), hasher)
{
Ok(bucket) => Some(mem::replace(unsafe { &mut bucket.as_mut().1 }, v)),
Err(slot) => {
unsafe {
self.table.insert_in_slot(hash, slot, (k, v));
}
None
}
}
}
}
```

当删除表中的数据时,原有的表大小不变,只有显式地调用 shrink_to_fit,才会让哈希表变小。

## HashSet

```rust
pub struct HashSet<T, S = DefaultHashBuilder, A: Allocator = Global> {
pub(crate) map: HashMap<T, (), S, A>,
}

```
33 changes: 33 additions & 0 deletions chapter09-hash/src/hash1-cap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use std::collections::HashMap;

fn main() {
let mut map = HashMap::new();
explain("empty", &map);

map.insert("a", 1);
explain("added 1", &map);

map.insert("b", 2);
map.insert("c", 3);
explain("added 3", &map);

map.insert("d", 4);
explain("added 4", &map);

// assert_eq!(map.get("a"), Some(1).as_ref());
assert_eq!(map.get(&"a"), Some(&1));
assert_eq!(map.get_key_value(&"b"), Some((&"b", &2)));

map.remove(&"a"); // 删除后就找不到了
assert_eq!(map.contains_key(&"a"), false);
assert_eq!(map.get(&"a"), None);
explain("removed", &map);

// shrink 后哈希表变小
map.shrink_to_fit();
explain("shrinked", &map);
}

fn explain<K, V>(name: &str, map: &HashMap<K, V>) {
println!("{}:len:{},cap:{}", name, map.len(), map.capacity())
}
38 changes: 38 additions & 0 deletions chapter09-hash/src/hash2-hashset.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use std::collections::HashSet;

fn main() {
let mut a: HashSet<i32> = vec![1i32, 2, 3].into_iter().collect();
let mut b: HashSet<i32> = vec![2i32, 3, 4].into_iter().collect();

assert!(a.insert(4));
assert!(a.contains(&4));

// 如果值已经存在,那么 `HashSet::insert()` 返回 false。
assert!(b.insert(4), "Value 4 is already in set B!");
// 改正 ^ 将此行注释掉。

b.insert(5);

// 若一个集合(collection)的元素类型实现了 `Debug`,那么该集合也就实现了 `Debug`。
// 这通常将元素打印成这样的格式 `[elem1, elem2, ...]
println!("A: {:?}", a);
println!("B: {:?}", b);

// 乱序打印 [1, 2, 3, 4, 5]。
println!("Union: {:?}", a.union(&b).collect::<Vec<&i32>>());

// 这将会打印出 [1]
println!("Difference: {:?}", a.difference(&b).collect::<Vec<&i32>>());

// 乱序打印 [2, 3, 4]。
println!(
"Intersection: {:?}",
a.intersection(&b).collect::<Vec<&i32>>()
);

// 打印 [1, 5]
println!(
"Symmetric Difference: {:?}",
a.symmetric_difference(&b).collect::<Vec<&i32>>()
);
}
31 changes: 31 additions & 0 deletions chapter09-hash/src/hash3-btreemap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use std::collections::BTreeMap;

fn main() {
let map = BTreeMap::new();
let mut map = explain("empty", map);

for i in 0..16usize {
map.insert(format!("Danny {}", i), i);
}

let mut map = explain("added", map);

map.remove("Danny 1");

let map = explain("remove 1", map);

for item in map.iter() {
println!("{:?}", item);
}
}

// BTreeMap 结构有 height,node 和 length
// 我们 transmute 打印之后,再 transmute 回去
fn explain<K, V>(name: &str, map: BTreeMap<K, V>) -> BTreeMap<K, V> {
let arr: [usize; 3] = unsafe { std::mem::transmute(map) };
println!(
"{}: height: {}, root node: 0x{:x}, len: 0x{:x}",
name, arr[0], arr[1], arr[2]
);
unsafe { std::mem::transmute(arr) }
}
14 changes: 14 additions & 0 deletions chapter10-error/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "chapter10-error"
version.workspace = true
edition.workspace = true
authors.workspace = true

[dependencies]
thiserror = "1.0"


[[bin]]
name = "error1"
path = "src/error1-transfer.rs"

Binary file added chapter10-error/error-situation.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 7505665

Please sign in to comment.