From ed3f77ce49c8dfe7ffc03d57aa7ed524aebc7818 Mon Sep 17 00:00:00 2001 From: sunface Date: Wed, 8 Dec 2021 15:38:06 +0800 Subject: [PATCH] update --- src/SUMMARY.md | 24 +- src/advance/global-variable.md | 39 +++ .../base-type/{others.md => char-bool.md} | 0 src/basic/base-type/function.md | 108 ++++++++ src/basic/base-type/statement-expression.md | 78 ++++++ src/basic/compound-type/enum.md | 30 +++ src/basic/compound-type/intro.md | 41 ++- src/basic/compound-type/struct.md | 250 +++++++++++++++++- src/basic/compound-type/tuple.md | 54 +++- src/basic/function-method.md | 1 - src/basic/method.md | 47 ++++ src/basic/statement-expression.md | 1 - src/basic/string-slice.md | 1 - src/compiler/attributes.md | 1 + src/img/.DS_Store | Bin 6148 -> 6148 bytes src/img/function-01.png | Bin 0 -> 16690 bytes src/img/struct-01.png | Bin 0 -> 23363 bytes src/style-guide/mark.md | 4 + .../posts/non-lexical-lifetime.md | 2 + 19 files changed, 664 insertions(+), 17 deletions(-) create mode 100644 src/advance/global-variable.md rename src/basic/base-type/{others.md => char-bool.md} (100%) create mode 100644 src/basic/base-type/function.md create mode 100644 src/basic/base-type/statement-expression.md delete mode 100644 src/basic/function-method.md create mode 100644 src/basic/method.md delete mode 100644 src/basic/statement-expression.md create mode 100644 src/compiler/attributes.md create mode 100644 src/img/function-01.png create mode 100644 src/img/struct-01.png create mode 100644 src/style-guide/mark.md create mode 100644 writing-material/posts/non-lexical-lifetime.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 7ec4e00a..d1780e6a 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -17,25 +17,27 @@ - [变量绑定与结构](basic/variable.md) - [基本类型](basic/base-type/index.md) - [数值类型](basic/base-type/numbers.md) - - [字符、布尔、元类型](basic/base-type/others.md) + - [字符、布尔、元类型](basic/base-type/char-bool.md) + - [语句与表达式](basic/base-type/statement-expression.md) + - [函数 todo](basic/base-type/function.md) - [所有权和借用](basic/ownership/index.md) - [所有权](basic/ownership/ownership.md) - [引用与借用](basic/ownership/borrowing.md) - [字符串与切片](basic/string-slice.md) - - [复合类型(todo)](basic/compound-type/intro.md) - - [结构体(todo)](basic/compound-type/struct.md) - - [枚举](basic/compound-type/enum.md) + - [复合类型](basic/compound-type/intro.md) - [元组](basic/compound-type/tuple.md) - - [数组](basic/compound-type/array.md) - - [类型转换](basic/type-converse.md) - - [函数与方法(todo)](basic/function-method.md) + - [结构体](basic/compound-type/struct.md) + - [枚举 todo](basic/compound-type/enum.md) + - [数组 todo](basic/compound-type/array.md) + - [类型转换 todo](basic/type-converse.md) + - [方法Method(todo)](basic/method.md) - [格式化输出(todo)](basic/formatted-output.md) - [流程控制(todo)](basic/flow-control.md) - [返回、异常和错误(todo)](basic/exception-error.md) - [模式匹配(todo)](basic/match-pattern.md) - [文档注释(todo)](basic/comment.md) - [包和模块(todo)](basic/crate-module.md) - - [语句与表达式(todo)](basic/statement-expression.md) + - [进阶语法 todo](advance/intro.md) - [生命周期(todo)](advance/lifetime.md) @@ -45,7 +47,7 @@ - [集合类型(todo)](advance/collection.md) - [函数式编程(todo)](advance/functional-programing.md) - [智能指针(todo)](advance/smart-pointer.md) - + - [全局变量](advance/global-variable.md) ## 专题内容,每个专题都配套一个小型项目进行实践 @@ -128,6 +130,7 @@ - [代码规范 doing](style-guide/intro.md) - [命名规范](style-guide/naming.md) - [代码风格(todo)](style-guide/code.md) + - [代码标记](style-guide/mark.md) - [Clippy](style-guide/clippy.md) - [面向对象 todo](object-oriented/intro.md) @@ -153,6 +156,9 @@ - [Benchmark性能测试(todo)](performance/benchmark.md) - [减少Runtime check(todo)](performance/runtime-check.md) +- [编译器 todo](compiler/intro.md) + - [常见属性标记](compiler/attributes.md) + - [标准库解析 todo](std/intro.md) - [如何寻找你想要的内容](std/search.md) diff --git a/src/advance/global-variable.md b/src/advance/global-variable.md new file mode 100644 index 00000000..4eb033ca --- /dev/null +++ b/src/advance/global-variable.md @@ -0,0 +1,39 @@ +# 全局变量 + +在一些场景,我们可能需要全局变量来简化状态共享的代码,包括全局ID,全局数据存储等等,下面我们来一一给出对应的实现方法。 + +## 全局唯一ID + +```rust +use std::sync::atomic::{Ordering, AtomicUsize}; + +struct Factory{ + factory_id: usize, +} + +static GLOBAL_ID_COUNTER: AtomicUsize = AtomicUsize::new(0); +// This gives large room for ids to overflow +// This code assumes that your app never would need many factories +const MAX_ID: usize = usize::MAX / 2; + +fn generate_id()->usize{ + // Check overflow twice to avoid growing of GLOBAL_ID_COUNTER after overflow. + let current_val = GLOBAL_ID_COUNTER.load(Ordering::Relaxed); + if current_val > MAX_ID{ + panic!("Factory ids overflowed"); + } + let next_id = GLOBAL_ID_COUNTER.fetch_add(1, Ordering::Relaxed); + if next_id > MAX_ID{ + panic!("Factory ids overflowed"); + } + next_id +} + +impl Factory{ + fn new()->Self{ + Self{ + factory_id: generate_id() + } + } +} +``` \ No newline at end of file diff --git a/src/basic/base-type/others.md b/src/basic/base-type/char-bool.md similarity index 100% rename from src/basic/base-type/others.md rename to src/basic/base-type/char-bool.md diff --git a/src/basic/base-type/function.md b/src/basic/base-type/function.md new file mode 100644 index 00000000..09212ada --- /dev/null +++ b/src/basic/base-type/function.md @@ -0,0 +1,108 @@ +# 函数 + +Rust的函数我们在之前已经见过不少,跟其他语言几乎没有什么区别。因此本章的学习之路将轻松和愉快,骚年们,请珍惜这种愉快,下一章你将体验到不一样的Rust。 + +在函数界,有一个函数只闻其名不闻其声,可以止小孩啼,在程序界只有`hello,world!`可以与之媲美,它就是`add`函数: + +```rust +fn add(i: i32, j: i32) -> i32 { + i + j + } +``` + +该函数如此简单,但是又是如此的五脏俱全,声明函数的关键字`fn`,函数名`add()`,参数`i`和`j`,参数类型和返回值类型都是`i32`,总之一切那么的普通,但是又那么的自信,直到你看到了下面这张图: + + + +当你看懂了这张图,其实就等于差不多完成了函数章节的学习。但是这么短的章节显然对不起读者老爷们的厚爱,所以我们来展开下。 + +函数有以下需要注意的点: +- 函数名和变量名使用[蛇形命名法(snake case)](../../style-guide/naming.md),例如`fn add_two() -> {}` +- 函数的位置可以随便放,Rust不关心我们在哪里定义了函数,只要有定义即可 +- 每个函数参数都需要标注类型 + +## 函数参数 + +Rust是强类型语言,因此需要你为每一个函数参数都标识出它的具体类型,例如: +```rust +fn main() { + another_function(5, 6.1); +} + +fn another_function(x: i32, y: f32) { + println!("The value of x is: {}", x); + println!("The value of y is: {}", y); +} +``` + +`another_function`函数有两个参数,其中`x`是`i32`类型,`y`是`f32`类型,然后在该函数内部,打印出这两个值。这里去掉`x`或者`y`的任何一个的类型,都会报错: +```rust +fn main() { + another_function(5, 6.1); +} + +fn another_function(x: i32, y) { + println!("The value of x is: {}", x); + println!("The value of y is: {}", y); +} +``` + +错误如下: +```console +error: expected one of `:`, `@`, or `|`, found `)` + --> src/main.rs:5:30 + | +5 | fn another_function(x: i32, y) { + | ^ expected one of `:`, `@`, or `|` // 期待以下符号之一 `:`, `@`, or `|` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) // 匿名参数在Rust 2018 edition中就已经移除 +help: if this is a parameter name, give it a type // 如果y是一个参数名,请给予它一个类型 + | +5 | fn another_function(x: i32, y: TypeName) { + | ~~~~~~~~~~~ +help: if this is a type, explicitly ignore the parameter name // 如果y是一个类型,请使用_忽略参数名 + | +5 | fn another_function(x: i32, _: y) { + | ~~~~ +``` + +## 函数返回 +在上一章节语句和表达式中,我们提到在Rust中,函数就是表达式,因此我们可以把函数的返回值直接赋给调用者。不像有些语言,会给返回值一个名称,在Rust中,只需要声明返回值的类型即可(在`->`之后,`{`之前})。 + +函数的返回值就是函数体最后一条表达式的返回值,当然我们也可以使用`return`提前返回,下面的函数使用最后一条表达式来返回一个值: +```rust +fn plus_five(x:i32) -> i32 { + x + 5 +} + +fn main() { + let x = plus_five(5); + + println!("The value of x is: {}", x); +} +``` + +`x + 5`是一条表达式,求值后,返回一个值,因为它是函数的最后一行,因此该表达式的值也是函数的返回值。 + +再来看两个重点: +1. `let x = add_five(5)`,说明我们用一个函数的返回值来初始化`x`变量,因此侧面说明了在Rust中函数也是表达式, 这种写法等同于`let x = 5 + 5;` +2. `x + 5`没有分号,因为它是一条表达式,这个在上一节中我们也有详细介绍 + +再来看一段代码,同时使用`return`和表达式作为返回值: +```rust +fn plus_or_substract(x:i32) -> i32 { + if x > 5 { + return x - 5 + } + + x + 5 +} + +fn main() { + let x = plus_or_substract(5); + + println!("The value of x is: {}", x); +} +``` + +`plus_or_substract`函数根据传入`x`的大小来决定是做加法还是减法,若`x > 5`则通过`return`提前返回`x - 5`的值,否则返回`x + 5`的值。 \ No newline at end of file diff --git a/src/basic/base-type/statement-expression.md b/src/basic/base-type/statement-expression.md new file mode 100644 index 00000000..8661df3c --- /dev/null +++ b/src/basic/base-type/statement-expression.md @@ -0,0 +1,78 @@ +# 语句和表达式 + +Rust的函数体是由一系列语句组成,然后最后由一个表达式来返回值,例如: +```rust +fn add_with_extra(x: i32, y: i32) -> i32 { + let x = x + 1; // 语句 + let y = y + 5; // 语句 + x + y // 表达式 +} +``` +语句会执行一些操作但是不会返回一个值,而表达式会在求值后返回一个值,因此在上述函数体的三行代码中,前两行是语句,最后一行是表达式。 + +对于Rust语言而言,**这种基于语句和表达式的方式是非常重要的,你需要能明确的区分这两个概念**, 但是对于其它很多语言而言,这两个往往无需区分。基于表达式是函数式语言的重要特征,表达式总要返回值。 + +在此之前,我们已经多次使用过语句和表达式, 先从语句讲起: + +## 语句 + +```rust +let a = 8; +let b: Vec = Vec::new(); +let (a, c) = ("hi", false); +``` + +以上都是语句,它们完成了一个具体的操作,但是并没有返回值,因此是语句。 + +由于`let`是语句,因此不能将let语句赋值给其它值,如下形式是错误的: +```rust +let b = (let a = 8); +``` + +错误如下: +```console +error: expected expression, found statement (`let`) // 期望表达式,确发现`let`语句 + --> src/main.rs:2:13 + | +2 | let b = let a = 8; + | ^^^^^^^^^ + | + = note: variable declaration using `let` is a statement `let`是一条语句 + +error[E0658]: `let` expressions in this position are experimental // 下面的`let`用法目前是试验性的,在稳定版中尚不能使用 + --> src/main.rs:2:13 + | +2 | let b = let a = 8; + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: you can write `matches!(, )` instead of `let = ` + +``` + +以上的错误告诉我们`let`是语句,不是表达式,因此它不返回值,也就不能给其它变量赋值。但是该错误还透漏了一个重要的信息,`let`作为表达式已经是试验功能了,也许不久的将来,我们在[`stable rust`](../../appendix/rust-dev.md)下可以这样使用。 + + +## 表达式 +表达式会进行求值,然后返回一个值。例如`5 + 6`,在求值后,返回值`11`,因此它就是一条表达式。表达式可以成为语句的一部分,例如`let y= 6`中,`6`就是一个表达式,它在求值后返回一个值`6`(有些反直觉,但是确实是表达式),调用一个函数是表达式,因为会返回一个值,调用宏也是表达式,用花括号包裹最终返回一个值的语句块也是表达式,总之,能返回值,它就是表达式,无论简单还是复杂。例如: +```rust +fn main() { + let y = { + let x = 3; + x + 1 + }; + + println!("The value of y is: {}", y); +} +``` + +其中我们把一个语句块表达式的值赋给了y,语句块长这样: +```rust +{ + let x = 3; + x + 1 +} +``` + +该语句块是表达式的原因是:它的最后一行是表达式,返回了`x + 1`的值,注意`x + 1`不能以分号结尾,否则就会从表达式变成语句, **表达式不能包含分号**。这一点非常重要,一旦你在表达式后加上分号,它就会变成一条语句,再也不会返回一个值,请牢记! + diff --git a/src/basic/compound-type/enum.md b/src/basic/compound-type/enum.md index 608029dd..7b18adf5 100644 --- a/src/basic/compound-type/enum.md +++ b/src/basic/compound-type/enum.md @@ -1 +1,31 @@ # 枚举 + + +## 枚举的一些妙用 + +#### 归一不同类型 +在实际项目中,我们有的时候会遇到用同一个函数去处理不同类型的场景,这些类型具有相似的方法,因此你可以在这个函数中用同一套代码进行处理, +但是问题是如果将这些类型传入此函数?类型该如何统一? + +例如以下代码,需要在同一个函数中处理`tcp`流和`tls`流: +```rust +func new (stream: TcpStream) { + let mut s = stream; + if tls { + s = negotiate_tls(stream) + } + + // websocket是一个WebSocket或者 + // WebSocket>类型 + websocket = WebSocket::from_raw_socket( + stream, ......) +} +``` + +因此,我们需要一个类型既能支持TcpStream,又能支持TlsStream,此时即可借用枚举类型来实现: +```rust +enum Websocket { + Tcp(Websocket), + Tls(Websocket>), +} +``` \ No newline at end of file diff --git a/src/basic/compound-type/intro.md b/src/basic/compound-type/intro.md index a91621d3..fe64747d 100644 --- a/src/basic/compound-type/intro.md +++ b/src/basic/compound-type/intro.md @@ -1 +1,40 @@ -# 复合类型(todo) +# 复合类型 + +行百里者半50,欢迎大家来到这里,虽然还不到中点,但是已经不远了。如果说之前学的基础数据类型是原子,那么本章将讲的数据类型可以认为是分子。 + +本章的重点在复合类型上,顾名思义,复合类型是由其它类型组合而来,最典型的就是结构体`struct`和枚举`enum`。例如一个2D的点`point(x,y)`似乎从两个数值类型组合而来。我们不想单独去维护这两个数值,而是希望把它们看作一个整体去认识和处理。 + +来看一段代码,它使用我们之前学过的内容来构建文件操作: +```rust +#![allow(unused_variables)] + + type File = String; + + fn open(f: &mut File) -> bool { + true + } + fn close(f: &mut File) -> bool { + true + } + + #[allow(dead_code)] + fn read(f: &mut File, save_to: &mut Vec) -> ! { + unimplemented!() + } + + fn main() { + let mut f1 = File::from("f1.txt"); + open(&mut f1); + //read(&mut f1, &mut vec![]); + close(&mut f1); + } + ``` + + 目前阶段非常类似原型设计:提供api接口,但是不去实现它们。因此在这个阶段我们需要排除一些编译器噪音,引入了`#![allow(unused_variables)]`属性标记,该标记会告诉编译器无视未使用的变量,不要抛出`warning`警告,具体的常见编译器属性你可以在这里查阅:[编译器属性标记](../../compiler/attributes.md). + + `read`函数也非常有趣,它返回一个`!`,这个表明该函数是一个发散函数,不会返回任何值,包括`()`,`unimplemented!()`告诉编译器该函数尚未实现,其实主要帮助我们快速完成主要代码,回头可以通过搜索这些标记来完成次要代码,类似的还有`todo!()`.当代码执行到这种语句使,编译器会直接报错,你可以反注释`read(&mut f1, &mut vec![]);`这行,然后再尝试运行程序。 + + 同时,从代码设计角度来看,关于文件操作的类型和函数散落的到处都是,特别是当文件属性和相关的操作多了后,更是难以管理,而且`open(&mut f1)`也远没有`f1.open()`好,因此这就是基本类型的局限性:**无法从更高的抽象层次去简化代码**。 + + +接下来,我们将引入结构体这个高级数据结构,来看看怎么样更好的解决这类问题,开始之前,先来看看何为`元组`. \ No newline at end of file diff --git a/src/basic/compound-type/struct.md b/src/basic/compound-type/struct.md index 9ed90ae3..2e049984 100644 --- a/src/basic/compound-type/struct.md +++ b/src/basic/compound-type/struct.md @@ -1,3 +1,249 @@ -# Struct(todo) +# 结构体 -## 结构体更新语法 \ No newline at end of file +在上一节,我们提到需要一个更高级的数据结构来帮助我们更好的抽象问题,而结构体`strct`恰恰就是这样的复合数据结构,它是由其它数据类型组合而来, 其它语言也有类似的数据结构,不过可能有不同的名称,例如`object`、`record`等。 + +结构体跟之前讲过的[元组](../base-type/tuple.md)有些相像:都是由多种类型组合而成。但是与元组不同的是,结构体可以为内部的每个字段起一个富有含义的名称。因此结构体更加灵活更加强大,你无需依赖这些字段的顺序来访问和解析它们。 + +## 结构体语法 +天下无敌的剑士往往也因为他有一炳无双之剑,既然结构体这么强大,那么我们就需要给它配套一套强大的语法,让用户能更好的驾驭。 + +#### 定义结构体 +定义结构体有几部分组成: +- 通过关键字`struct`定义 +- 一个清晰明确的结构体`名称` +- 数个具名的结构体`字段` + +例如以下结构体定义了某网站的用户: +```rust +struct User { + active: bool, + username: String, + email: String, + sign_in_count: u64, +} +``` +该结构体名称是`User`,拥有4个具名的字段,且每个字段都有对应的类型声明,例如`username`代表了用户名,是一个可变的`String`类型。 + +#### 创建结构体实例 +为了使用上述结构体,我们需要创建`User`结构体的`实例`: +```rust + let user1 = User { + email: String::from("someone@example.com"), + username: String::from("someusername123"), + active: true, + sign_in_count: 1, +}; +``` +有几点值得注意: +1. 初始化实例时,需要为每个字段都进行初始化 +2. 初始化时的字段顺序无需按照定义的顺序来 + +#### 访问结构体字段 +通过`.`操作符即可访问结构体实例内部的字段值,并且也可以修改它们: +```rust + let mut user1 = User { + email: String::from("someone@example.com"), + username: String::from("someusername123"), + active: true, + sign_in_count: 1, + }; + + user1.email = String::from("anotheremail@example.com"); +``` +需要注意的是,必须要将整个结构体都声明为可变的,才能修改它,Rust不允许单独将某个字段标记为可变: `let mut user1 = User {...}`. + +#### 简化结构体创建 +先看以下这个函数: +```rust +fn build_user(email: String, username: String) -> User { + User { + email: email, + username: username, + active: true, + sign_in_count: 1, + } +} +``` +它接收两个字符串参数:`email`和`username`,然后使用它们来创建一个`User`结构体,并且返回。可以注意到这两行:`email: email`和`username: username`,非常的扎眼,因为实在太啰嗦了,如果你从typscript过来,肯定会鄙视Rust一番,不过好在,它也不是无可救药: +```rust +fn build_user(email: String, username: String) -> User { + User { + email, + username, + active: true, + sign_in_count: 1, + } +} +``` +如上所示,当函数参数和结构体字段同名时,可以直接使用缩略的方式进行初始化,跟`typescript`中一模一样. + + +#### 结构体更新语法 +在实际场景中,有一种情况很常见:根据已有的结构体实例,创建新的结构体实例,例如根据已有的`user1`实例来构建`user2`: +```rust + let user2 = User { + active: user1.active, + username: user1.username, + email: String::from("another@example.com"), + sign_in_count: user1.sign_in_count, + }; +``` + +老话重提,如果你从typescript过来,肯定觉得啰嗦爆了,手动把user1的三个字段逐个赋值给user2,好在Rust为我们提供了`结构体更新语法`: +```rust + let user2 = User { + email: String::from("another@example.com"), + ..user1 + }; +``` +因为`user2`仅仅在`email`上与`user1`不同,因此我们只需要对`email`进行赋值,剩下的通过结构体更新语法`..user1`即可完成。 + +`..`语法说明我们没有显示声明的字段全部从`user1`中自动获取。需要注意的是`..user1`必须在结构体的尾部使用。 + +> 结构体更新语法跟赋值语句`=`非常相像,因此在上面代码中,`user1`的部分字段所有权被转移到`user2`中:`username`字段发生了所有权转移,作为结果,`user1`无法再被使用。 +> +> 聪明的读者肯定要发问了:明明有三个字段进行了自动赋值,为何只有`username`发生了所有权转移? +> +> 仔细回想一下[所有权](../ownership/ownership.md)那一节的内容,我们提到了Copy特征:实现了Copy特征的类型无需所有权转移,可以直接在赋值时进行 +> 数据拷贝,其中`bool`和`u64`类型就实现了`Copy`特征,因此`active`和`sign_in_count`字段在赋值给user2时,仅仅发生了拷贝,而不是所有权转移. +> +> 值的注意的是:`username`所有权被转移给了`user2`,导致了`user1`无法再被使用,但是并不代表`user1`内部的字段不能被急需使用,例如: + +```rust + let user1 = User { + email: String::from("someone@example.com"), + username: String::from("someusername123"), + active: true, + sign_in_count: 1, + }; + + let user2 = User { + active: user1.active, + username: user1.username, + email: String::from("another@example.com"), + sign_in_count: user1.sign_in_count, + }; + + println!("{}", user1.active); + + // 下面这行会报错 + //println!("{}", user1); +``` + +## 结构体的内存排列 + +先看以下代码: +```rust +#[derive(Debug)] + struct File { + name: String, + data: Vec, + } + + fn main() { + let f1 = File { + name: String::from("f1.txt"), + data: Vec::new(), + }; + + let f1_name = &f1.name; + let f1_length = &f1.data.len(); + + println!("{:?}", f1); + println!("{} is {} bytes long", f1_name, f1_length); + } +``` + +上面定义的`File`结构体在内存中的排列如下图所示: + + +从图中可以清晰的看出`File`结构体两个字段`name`和`data`分别拥有底层两个`[u8]`数组的所有权(`String`类型的底层也是`[u8]`数组),通过`ptr`指针指向底层数组的内存地址,这里你可以把`ptr`指针理解为Rust中的引用类型。 + +该图片也侧面印证了:把结构体中具有所有权的字段转移出去后,将无法再访问该字段,但是可以正常访问其它的字段. + +## 元组结构体(Tuple Struct) + +结构体必须要有名称,但是结构体的字段可以没有名称,这种结构体长得很像元组,因此被称为元组结构体,例如: +```rust + struct Color(i32, i32, i32); + struct Point(i32, i32, i32); + + let black = Color(0, 0, 0); + let origin = Point(0, 0, 0); +``` + +元组结构体在你希望有一个整体名称,但是又不关心里面字段的名称时将非常有用。例如上面的`Point`元组结构体,众所周知3D点是`(x,y,x)`形式的坐标点,因此我们无需再为内部的字段逐一命名为:`x`,`y`,`z`。 + +## 元结构体(Unit-like Struct) +还记得之前讲过的基本没啥用的[元类型](../base-type/char-bool.md#元类型)吧? 元结构体就跟它很像,没有任何字段和属性,但是好在,它还挺有用。 + +如果你定义一个类型,但是不关心该类型的内容, 只关心它的行为时,就可以使用`元结构体`: +```rust +struct AlwaysEqual; + +let subject = AlwaysEqual; + +// 我们不关心为AlwaysEqual的字段数据,只关心它的行为,因此将它声明为元结构体,然后再为它实现某个特征 +impl AlwaysEqual for SomeTrait { + +} +``` + + +## 结构体数据的所有权 + +在之前的`User` 结构体的定义中,我们使用了自身拥有所有权的 `String` 类型而不是基于引用的`&str` 字符串切片类型。这是一个有意而为之的选择,因为我们想要这个结构体拥有它所有的数据,而不是从其它地方借用数据。 + +你也可以让`User`结构体从其它对象借用数据,不过这么做,就需要引入**生命周期**这个新概念(也是一个复杂的概念),简而言之,生命周期能确保结构体的作用范围要比它所借用的数据的作用范围要大。 + +总之,如果你想在结构体中使用一个引用,就必须加上生命周期,否则就会报错: + +```rust +struct User { + username: &str, + email: &str, + sign_in_count: u64, + active: bool, +} + +fn main() { + let user1 = User { + email: "someone@example.com", + username: "someusername123", + active: true, + sign_in_count: 1, + }; +} +``` + +编译器会抱怨它需要生命周期标识符: + +```console +error[E0106]: missing lifetime specifier + --> src/main.rs:2:15 + | +2 | username: &str, + | ^ expected named lifetime parameter // 需要一个生命周期 + | +help: consider introducing a named lifetime parameter // 考虑像下面的代码这样引入一个生命周期 + | +1 ~ struct User<'a> { +2 ~ username: &'a str, + | + +error[E0106]: missing lifetime specifier + --> src/main.rs:3:12 + | +3 | email: &str, + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +1 ~ struct User<'a> { +2 | username: &str, +3 ~ email: &'a str, + | +``` + + +未来在[生命周期](../../advance/lifetime.md)中会讲到如何修复这个问题以便在结构体中存储引用,不过在那之前,我们会避免在结构体中使用引用类型。 \ No newline at end of file diff --git a/src/basic/compound-type/tuple.md b/src/basic/compound-type/tuple.md index 5e2fda38..6296c872 100644 --- a/src/basic/compound-type/tuple.md +++ b/src/basic/compound-type/tuple.md @@ -1,6 +1,51 @@ # 元组 -可以使用元组返回多个值 +元组也是复合类型的一种,因此它是由多种类型组合到一起形成的。元组的长度是固定的,且在声明后,无法进行伸缩。 + +通过以下语法可以创建一个元组: +```rust +fn main() { + let tup: (i32, f64, u8) = (500, 6.4, 1); +} +``` + +变量`tup`被绑定了一个元组值`(500, 6.4, 1)`,该元组的类型是`(i32, f64, u8)`,看到没?元组是用括号将多个类型组合到一起,简单吧? + +从元组中获取值有两种方式: + +### 用模式匹配解构元组 + +```rust +fn main() { + let tup = (500, 6.4, 1); + + let (x, y, z) = tup; + + println!("The value of y is: {}", y); +} +``` + +上述代码首先创建一个元组,然后将其绑定到`tup`上,接着使用`let (x, y, z) = tup;`来完成一次模式匹配,因为元组是(n1,n2,n3)形式的,因此我们用一模一样的`(x,y,z)`形式来进行匹配,然后把元组中对应的值绑定到变量`x`,`y`,`z`上,这就是解构:用同样的形式把一个复杂对象中子值匹配出来。 + +### 用`.`来访问元组 + +模式匹配可以让我们一次性把元组全部获取出来,如果想要访问某个元素,那模式匹配就略显繁琐,对此,Rust提供了`.`的访问方式: +```rust +fn main() { + let x: (i32, f64, u8) = (500, 6.4, 1); + + let five_hundred = x.0; + + let six_point_four = x.1; + + let one = x.2; +} +``` +和其它语言的数组、字符串一样,元组的索引从0开始。 + +### 元组的使用示例 +元组在函数返回值场景很常用,例如下面的代码,可以使用元组返回多个值: + ```rust fn main() { let s1 = String::from("hello"); @@ -15,4 +60,9 @@ fn calculate_length(s: String) -> (String, usize) { (s, length) } -``` \ No newline at end of file +``` + +`calculate_length`函数接收`s1`字符串的所有权,然后计算字符串的长度,接着把字符串所有权和字符串长度返回给`s2`和`len`变量。 + +对于其他语言,元组可以用来声明一个3D点,例如`Point(10,20,30)`,虽然使用Rust元组也可以做到:`(10,20,30)`,但是这样写有个非常重大的缺陷: +不具备任何清晰的含义,在下一章节中,会提到一种`元组结构体`,可以解决这个问题。 \ No newline at end of file diff --git a/src/basic/function-method.md b/src/basic/function-method.md deleted file mode 100644 index c11086c4..00000000 --- a/src/basic/function-method.md +++ /dev/null @@ -1 +0,0 @@ -# function-method.md \ No newline at end of file diff --git a/src/basic/method.md b/src/basic/method.md new file mode 100644 index 00000000..e72332c6 --- /dev/null +++ b/src/basic/method.md @@ -0,0 +1,47 @@ +# function-method.md + +## 函数返回 + +SPECIAL RETURN TYPES IN RUST + +If you are new to the language, some return types are difficult to interpret. These are also especially difficult to search for because they are made from symbols rather than words. + +Known as the unit type, () formally is a zero-length tuple. It is used to express that a function returns no value. Functions that appear to have no return type return (), and expressions that are terminated with a semicolon (;) return (). For example, the report() function in the following code block returns the unit type implicitly: +```rust +use std::fmt::Debug; + +fn report(item: T) { + println!("{:?}", item); + +} +``` + +And this example returns the unit type explicitly: + +```rust +fn clear(text: &mut String) -> () { + *text = String::from(""); +} +``` + +The unit type often occurs in error messages. It’s common to forget that the last expression of a function shouldn’t end with a semicolon. + +The exclamation symbol, !, is known as the “Never” type. Never indicates that a function never returns, especially when it is guaranteed to crash. For example, take this code: + +```rust +fn dead_end() -> ! { + panic!("you have reached a dead end"); +} +``` + +The following example creates an infinite loop that prevents the function from returning: + +```rust +fn forever() -> ! { + loop { + //... + }; +} +``` + +As with the unit type, Never sometimes occurs within error messages. The Rust compiler complains about mismatched types when you forget to add a break in your loop block if you’ve indicated that the function returns a non-Never type. \ No newline at end of file diff --git a/src/basic/statement-expression.md b/src/basic/statement-expression.md deleted file mode 100644 index 99d6720e..00000000 --- a/src/basic/statement-expression.md +++ /dev/null @@ -1 +0,0 @@ -# statement-expression.md \ No newline at end of file diff --git a/src/basic/string-slice.md b/src/basic/string-slice.md index 2df390eb..8fc84be1 100644 --- a/src/basic/string-slice.md +++ b/src/basic/string-slice.md @@ -260,7 +260,6 @@ fn say_hello(s: &str) { | = help: the trait `Index<{integer}>` is not implemented for `String` ``` -https://rustwiki.org/en/book/ch08-02-strings.html#storing-utf-8-encoded-text-with-strings #### 深入字符串内部 字符串的底层的数据存储格式实际上是[u8],一个字节数组。对于`let hello = String::from("Hola");`这行代码来说,`hello`的长度是`4`个字节,因为`"hola"`中的每个字母在UTF8编码中仅占用1个字节,但是对于下面的代码呢? diff --git a/src/compiler/attributes.md b/src/compiler/attributes.md new file mode 100644 index 00000000..644cb3e5 --- /dev/null +++ b/src/compiler/attributes.md @@ -0,0 +1 @@ +# 常见属性标记 diff --git a/src/img/.DS_Store b/src/img/.DS_Store index 08567d1190259c4179390402a736b2348e8ad99e..81b3f334635c5160a711ce9f91f91becb62566fa 100644 GIT binary patch delta 110 zcmZoMXfc@J&&a(oU^g=(_hudzRVH>`hGK>ihN8(bEXuCk3=9l<|G@yrVqk#EF_bbS w1J&p<7%&(z=rI&9V&;RS7UKF#ZJ6P@NkK(-}9jbNuB80CtcdrvLx| delta 28 kcmZoMXfc@J&&atkU^g=(=Vl%jRi=$)*BCdmbNuB80DhVX(EtDd diff --git a/src/img/function-01.png b/src/img/function-01.png new file mode 100644 index 0000000000000000000000000000000000000000..c9fbd42f41f44a8556852f83a95c1eee16a1335e GIT binary patch literal 16690 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

1);aFD;2FnZlT!V-ir^BK5AUi0Zpee2c z|7IpZG>H#TdKo>)gqfW|y`$W@4AdX80K|Ui5+G6L4~_1b=2z`>5>y4THvniSKAw7o zl4~R%1;ET(oY|A!epy%ymuEu&+;WT(sz8;t6Tsw^5*9=v%T~dv z6xiG8LRfl|`<9dwSaJmk=buPy?7jZc3E1H%y^$LS!aMxD)#CxVEbq;z+e1ys{a8%t z>M_6{_ZG#!{^yMyt-H~gmV?EIg;O>GKyB|R+-1iP;7-k(9CkbXcqn2L1b}s}_o8U6 znG$_iS$>-XxO@?}XrkJ#9!zOaA7u7}M1MTEwoV2?xizkt*P4hx9$RkC>Tdh@Dip4d zK-Da>^}-ugth~uAczXrAKi1Bqyz2cHG%{NBf6d4%d6_%DuH|Rz1N{_s#-}le?Om}* zfrMUetosKNlYh7n;*Xzv4O_|@C)KlmWGZ_E-s;KoL0-Hk|Jv(5!%Dc_GQQ< zXi-G#R&y4|xYrww*2?0UmV9mgX>?q~L%|F`p5F!u{ar2t1_P4i1}Smjd}MOm4uBo6 z*bX|;s6AR7iq-}%SMe@XXJ)@d_X*@J|JI0{-*SE({;a>!q<4wuRa9(O^dMD8D~Gb# zh)8tL04-G2MU}bY&mPu%Y2cOW3;A?=D90%l8g$>T1kt|V?!*y9D&8HAW6E+!y=q)g zMlW83m)?payiPb^T}lIe{(hl+Sckx`2dNf6W}BQ>@6cQ_zL9`R5t?f<(=iV%bLq?P zZZwbAweU?9Ix^mAw4^}PcB?OS_d3yxE`Xx;*h?aC*ulwB9Rm1HsSA)N5WzsZQJ!d= zN>Mh(wwIYsyl*2xRQUK~NUajbo#PDRS$EC+b-hVZMT^xA{J>x+B=`WtwyEKzIEv;v7)Mo1W^jTIPvL8 z;_|Pxskg^m`=ClVO-LL2T^jjftOqLr_S@>lN?KA8JJ@SbjrcMD)s@j;8@R}o+mJzu z6Rv<<2fKl~w;|2)IdT2BPPu|KxN_su#GZoFAzEyDuT?##!KUhjJ1Lm-y-L0pW^Nj- zH7#b3b;pkakkkxu(EAXcl-w-&x^1cC{$#c#I}E(HMZ6+qY;Z&N1Y~h*dS&$i98`+A zo-aVwXx6(_hcxV}`uX*j4AXZ7+ z8T1Hv7B8T=DVLK6cCUZ4XO~w}j#Gbgbk>bo2SrTOkRW3a2&s&$w3~p6E@c_t@dOsm zhV`MH(un#XFX7I6N(AL&7(T39i8u(D0}^^MIVFV=j*)j--Y#IzFB=Ph%{vF>M-0ll z`Kfnm05rMF@pT-eQk3s1UnaSbwD^TxF5V(80kP__(*%z7(xOPi%~Or(d%t^!hk1sO zMqzU8)@eV3$QomI^CAyku3{mTxHrQ*_-jJh0!9=lPK5E%qArNGwp{vjTmsspnWwLpCL=7=2n^7^HVvcr^PQy9n= zOx2Y#g53=M-YbV-SVbV+xEv`7nxbeDjDh;&JV z5@(IiyWel`@7w#FbA8X{!wmmey?$}u_u`GZs@xqsDm*kav^xs&(wb;!==0$FAr3nD zNy?GQ3_ft3<@H_B&}chR|KD;NbrVBF!JTY}3mn4F0cE#< zLb)LVLL6NDygd9+HV8MA8_Egg=H%jGhjPK70x)iF$iM!h2er9aTER4>W&c$d_)V1F z28ncradLWicyM^|a3EZ)Ik|*{givL0bF+gd*j>GxkY=9jPOc39QGztw)xyQr8EK1f zf}lz?Ge@`~Md?9H|LKCG^S_IAa{bpZfdS+6G;`+U;((&M^!Gtai+?}o?B?R|w{lAh zPPhZy5$=R^1i^MX2sh{ngjv_t z$r9n=%JQFHfJ>Vp;iB|l*0|WA0_;$JEhrSm%?sn^c>?8zL81RVs)DezwetG!9_4|; zxVZnzqhQHcnjy{pj}Kc~z^o81j%J|4wvJ}ja873@YkJ7PhY==)a6q_#ib3mm{_}MO zDJgXqgq5uWxZ$cPCkauIk>ckP;^$}Q=HU9>yeE+EKd#>Efkw&b_uK`r~gD+wlV>k8)B z>t7q`8T`e+zB$-J{w^MvnFVT7h|*i2Rs$Tg;GfI3|IK*(U)B7t_dRUjpwR!#D*2}x zSA-SP!^{OPVGYLa|F{Y{|HsB7oZR6q|Ec-TW-eyH7QtOyMd__v5RQ<4Rt((P)e3?{ z{OdQ=`uQJ=bTxDT-;c)s-Rk(KoB!Qt{FjaJ|7SG*HPRL~W=_^{V6-{^c7_vW-u{_q z&j0rk_>4SxtH#fw3H8KS8pFZTB(UXK0D&ZAV=qM=jC9&1tVw5TV zd>qVjD|Um3de##j{t6zFWJze6t%-5tRm!=exzXpXy2u21)jxL3l=4WT=aK?R^!(ATJaExWguiqA> zm6T_u8D_?#%U2?9!VDyiBkm4iu5sLYRa#2ZGv)eujq-s6@lObieH|K(=DWAKgMY3b zQ6X{Br{tgBK*SzS$(x$Y6%sN^zv$ogOHiD${#Zzbdf|JvY!F1-)YFntYdm+NGmil$ zNDFIHK1S+Om#0Vo!_3&NhuEUD62v%krVv}4NNpT-@K!$7(@0Dq%mf|2)9vJ2_lai4 z%&PVJzsYE8vt+y)$q*Six@?nW3}FtB(@5w)g=2k9{)!U>3448$H---BmDv0+AKlRK z5P`^gLg^uilXCROM9`~d-f92CJf~g-XQpT~Wn|K#jP}%W?A<2ahK1`Nv$YHE&5R0l zBP+YRb)xc}{(B$hrIw*PC*TgTn^HTgCq%8w91qvI!_IH{r-FC>BUw3OOd&(iIhuQ~ zb{I#_=$z?PQojhy{KCim3|B)ui{kkw;#;ho`Vnqh`v<$hn*Uek-r2u1l&MBkh=?>kkLf6~>JmDA@7m5F17 z>K+Sa1YGSkxBH(h1YE6h`l&vqlh)Q&hc{uGeOb?I9z6Hm$qFG>H)Q(Kv%J(+<66{W z4E>_Vmel+Ecb-TVZzm;bX-9rB z#|qY%G$a(WB!lx%?YhE*qW(C0d97_}Qw`pdQMbuGbf610{j&b#qn}!_o27-{19WvZ z@`zmK@LZgr>{2@+)I8JRsWV6r-nxjb_!GI8A4^$UIzDoF)=u=$X0p_utTtsuP+R+v zf=lB9V6J~kGm3MN)X;xYUGNoHP%SQL}YJ297(R-Js zLO=hO4?4>8p7aBCv$`qD7cLCFZQs3U>6NYBpA5y<=mu_XY)~9~f*I;qA#L-yZ*DM4 zv(P^}YlTd`%@@fW-Wd*CKa0qF5$8qYLeD&EU3Zhb#86TK-@#%(?B8If3t9OnR&><0x=Mm^PifxFtQD%of*ab^ zgf!>(4S}U;X&d2Tljh=ZHQsw01;H6l-&m0+!0z&je{+q?L0vXv#hqfQ&lF-vOI2Fr zi=%nZ%CF6a4V$GI>=X#jkG2~`;hMAMV(#VSiAcCm*Sgq)yj z-5C{c^6>$dMMeY9PDX&79Fj|}L%Q?R3vA**Hgf!*bo(AiOo^B^>B`u2ffO<0=K}~2 zgrg$^30I0T#cm*ttY>C)d1doAr(Z4VVfZ~Sh#rbCuQhLyggk%pVh5vE)s`~ixUNm*&7ux0pyV@%|Bv~8l-P!)AYw09$10!%hKw4#jpFXz2lV;pk zndw=>f+}@y%}!QY@W?|p&fDbo1?capOnC2{zUfnl?@Lf*LR7wY>R!PPUarWY`(Q2E zt0O|IXNWm-Z=vAbC$Qgef_Cs*WznO(e%B9KVZiB4T1Rb?X%QA3^0$Xl>{V3cXriiuXiH?-$AfwzB92XJx5n4Y=JmABEsN+r zOV+Qh{ApNjpG~2@RV_Pd8KFjti}ib``fyyHvX;-L4q0tt%nJzP^JD*Ncj#Wh!cVfS z)i>Z70+%#c8gzBtlHQD~7sZX)V6q2R?8-Jj3i;~5U-f#l1x`L!vn?kcge{wQusE06 zVcNS7CJ5)@ZzB$MbFoNiOZ{Q1+8VaJ6if+}5sETq=sTMu`?ia_a`SM{%xId;(%#S0byI-HJ613po#xILC`WP&RPe07LC|QGP z9op1NzdkK``^9BEAFhwxz53=-dIFUCN#3>Jv)`^ZC-rY>4@#@X7o{nwlpmNfI0E~1 z#5B=%DY0t05P4KUR!c`Y@Qex1j$O@?Qp8a0=i^z2X;Y}4^r);hd{R<&xD7iPW#;sOXLMboY* ze_DmCI}>WKY{}pi_VGl2q+42>`u(*BVdk?l*T35;t3@k!czv=RrE7x4a4XHgrSv>+Oh8!aNq(QUUwgxx!(;>coRmL%eK6AB z%LZo$RvuVXef)Lz`|Rv%>GwlJ*0r+@uQ<-W?yh={8ldT=a!^I&aDd`9jZ9N2I+T(( z?D9^QOJpTYjw1?I#<53s#eTh&wfGUi=~VgNpX$w1v^8MLb#|CPM)X-WHGII<{&@!* zW72$PN|N36c%1+{H z*9i9yJx*a%M^!Uk@tYMnIabWFcrcSck3=*WY*lJzcgBCH=qE{V+TPNQVpOJoc$()$}$3L+bb+snT}2+_(xR1{(Iyy*Jb3{r4X-hfgMu~Ew@CJyI?nOtom3R|Zt zte!uVT>kZ|7iZ)M_^;ynSHRZ>ZETQ)$dx2?o2Q)p36qnx6Cn0>j3TCv?JbJElQ(wG zqkCgkf|f?y?bN(rUM=GL3(Z0|whQ0eF{Uf3v~;1hHI8w?K%es1(~b*-NODnH+?0AP z3OFh6e2e-{NMtlP^eRGP!iZ>1iJ!O>OGIMY-YV8aXNoU9i>B(kyZVMrDzF|bEdfVG z)rN&k;_k2m&jpte;(S>!K6Ti?a=(s^9WW=BHZ4%C$VV}+s}u$_wf&l34Y=0y|KWL3 z1dL=F`>`7jmCEZMpU(xsfVfy{kim!d!vgdOt0}*Gfl1Wvz4P9Cy*QS}7L4lDETw#( zm+N=8;;T8EoJ{W36Bil**Au%uEMP+pUgv%^i3BmMLYy7rhz7PXS#pqswszS(4+#Dy z64Jk3EoJd!+zi#7?T(o^@y&f`p^Rh==XO0|m93@k)p)gjp`V4AUMD?8JV_k4WloIH z%Am|r)1E3#Qvl)TwQT!<8)7&9O`iwtmj;^3Yu>7lUzy_-&i9O>R_w@zBT*JLghK+v zXRJ25cPHhEMTyN_zzff0SLXBDeSMCTcO?5y=;*>#!!YhJ7J&F^!QH1};eF{=`qGjk zD#-{q*wJ5bl+;N0G_DD9iO#-w5Q8=Ey6fG0y~|it$1B3^($c!H>Mn%LL5jOIw+N>!B&B;g8*)P)qR_WH^}z8{YYj!Zof71dg1?yW2;aue|Q zy>9*H^T2)1nvC^^9MF}g9ulXRd~t_Ders>{gp&I#!HbF0_nuyuHuxsV@0_LIIJuGr z6dukV$<2C%P1Q9(*j1tz7A+b`B|rQ)xJgvTB1fbu7e?^gM=u!9D*9I`A0U!%^mU8b z^O!@3+1}`g`D8xP*3PS@NdKyusjFR|mzSq!@qSb{$NBtAXAsA1hk5lRJqEE*|I7PN z?@N6-^1a3*3D0$q&9mc>!>N8ZbT9fNWu)RJFAMikEXgmCEY+g2uXJE*wB?lck?N~5 z#UrAxH79t}hTO-j>gOE(jH~jh__%&Q0Um56e!uP$diM~n;A95j?Q(VIf(cxWZ-~jN zTxO-vglJX66XFt9N*NZxlEINJnl1(gT#X%9m_$R=7xR0Vyz+6A3-j}ja7G(b2V^X` zCYAbc8zV|lb<3}UaD6yUIXUbV4qb^QccQX?oi}w|yldeRQ~YL2pO*O*veL zN-Q;X$#s(8zb}B1YkSeU>g1M>oHOUI-FnTafK~CJ;025Z>jAGeXKV<~3)A;oarTS~ z=Ay4OVY^7duh==xAA`c*$1zrK;S}%xNunsBEslju_1M)K(Ng^`+QzT`)85{2s?gBd zV+zfW>uZn;z=ib#D?z}<;UBNN!&v2c1f1bf0|S-@8P;AWt_Eg&eQ7DKhL)?4LL7v$ zMu|8d39G8hFJ&eBiOs{eknAoKxmYE9g_k)`zFIon!Ml zD-sh~D(^F~2V$Nq8b@?XK6cFNswN`{nnw5P3^W}zuO77}(i^mbUEtECjcoug!?uVE zAcC0BgtnhJGlZ?V(xwbK=)#Nb1TX=}kZMss3&K@9iALb$fK@IV(s6#2p~c;JQhD>+ zqbGXCWLQd0l5G9Tzlx_T!$2d!t37LbkVbsC&e;yq zu2B*yO{Efd%au%i{z@@32I{e>$awYA{)Ya}O84-Ma6sOa6+_SU zyf@?F%zj&0yF892gY&LQ{z>uga#?EJakk@T!z{mpi`IIz;amnZ099=SHuB3`c-Bx) z+d(Nn)^yP40Rk!u8A%Y%Q{jMRZ!yX{WD0HJLtcRVsazTrX#$VQ`wGO&)+WADO{gRT z9d!kJQU<(3O#as4?`Qr2xCkDG$gcorjLHsTz68Hul#kc!V7-SkURT^m)1e<(M{dWV zyHF4Z%vx#!p3b3k4AX6EzHxKpE=RB7J>bhy$;uld>qx4KcOpYWW${4aonf-dAd~^;52N>edX@e zICvswlLfNS_&%+wNH!1)3Y}jb%o$v`=(aHYZLmu3vq;87W%A28yV|>wHM49Y*KmD8 zHjcJ{D{mpA397nM7+rkj_iJ!w@sPmL-Dm9o6)v;6Jp z7xO@&Lh zWLf)b)`l09Tf=r=*ymolF{TiXdMAEF2ME0b`lsY=ehl{5+aK#U|4nLD<|znX`PkbR zJp8$@s)mrJKOQ+uj1%>ku1=?95C4Ok0~c zL@dmLhdk}%Vxu8Emsrv>6OsNBNAqO}^LXh+hKTsa0kI^ROd~1b1pkh*6D@d6lI)&L zwH_OYqCHIi0mEjeG#@t8F;P0BGB%cnpcs zAg3nuT;^A$0=8uXzj^@-y+;y4nMK6$R3VOveNrRm(2#nX;@834+~=Q+sFW;PM>k?u zvK`DXfH?xHS`62y15$(~G56YwCQRVmyy*97eSmLj>$kKSh@P1SpWt6H`q;ip_ukSC zYy8C-GL_tr<+PV=j5_keYnnmz z)9dz<7;kc!$Mo20+6Z;O0dsy(UHugL)uu5D@19Oh${3sQA{) zBz+zVg6{CzT@ShVKIFx7Zvxr~m>DTyr*E_#w91+T2$vzh0tq$#{(I;`f^3PMl;gF!2n466cw6_>Of)~zGG`?oVFs9j++#i?4!0A_Lc_{G0s zZ$vv4TC*PY{NN)1@s4qULx~c)1>B{$z-<@`E}l=k-r;?;hHvv+xf#p1PAu7k zx%{QGQxhtwITWgHmL~vEi}ux&RyTu>xy*s4P%=Ug z$EB3%K53T4q0@vdbQH5t%4m?uSmT5EoI@gejRq${qWxz_i8@1$*`1IWK)^(CWkrVc zTGg($YbMv`725J@koOPxKN~;lv_lK*mZ>V#GQ{FA$pX-_UZnK>iBzH!uFYIo`Prg| z;ZcHYlA7I;DaY=HLjkHt*{++Dfa@oP%RA%i$Z?-CMg>in9~@a1zpli5yBnG|G?lc6 zc-fgilv;lm_?p!d*6_}w%M9nQo6c2Btl>3U%*X^cG1lfnLGldQLy&_5P-uI*1Wh51 zKW|K~ge;>Wu%LjYvcWWz7P>z8+xKtcJ;ba?`elojgLP8=lMa!Z`OUZVf6y^w1^zTY zYXPqitnkDR4n%a6siVexDsG61#fz*7f${ z%(FhmDJ#vspCBf)sI;k|B)JT*L&l`9Zx_Z2TJsRh`OjqbIWWgGS%! zE3xxkGf0Ncw#PK$Wx@6RElj^7t=EZ$);x-elv*gCJqu(TXs3F>z9a;8dJ#p}8^C-8 z*zhk|)mQ=$|NB8s>Mb^N0t5WCZJ(yvqdSFba;zzAcj-WggXj0{^y_Xnfh2&`1hBEu zo97ZcOwkxr;6-QZASE$B3n1FE%7fdIPa3}ezGA37HN55;`qE@+)jfEyv=qb-$@7u? zBq78f_0jnLt!;b?uRXh z4xWl!D)Jf$LhU!9@sFjJe`WU^nFL%Yb^FtYXnKjpfh752BzpYO;!;ZbWTQ;~aokQL zpbRb9DFI0W2)zX zY4e*<@%Bs3D4f|T$-@4Wz*pV|=x0;g%>vhT+k_Y!w>c~ zs|5bCKyP_v^SBPW@9%I3+`r$!jQ(aCmg07mEZEBaDGj3%5Msa^H(_KQ{Q;ROf6s{x zx-oUcEDc^59mCyll?6S$QA%2{uK^OBt=dJz2FzT?+9UV-aBlghh=0}i(dYP=i0h+eh%mGS;RBh$oxd0bO8TsMN7rXo}A4=y3xvTeHVEK z)|i94M-6B_)1-Uu1VL8SL%kVa6Q&A+-SR6Zg64s-h)>eWN7c+Q-W4P)gSgxGAt^{N zCDa*8xOc|A6SV~-Vx;;5E;rS9p-IF)8j+hIY1RVVCkyGMd?^86%%~PfYhX`D>16=| zs(Gt8Rx1VUg@Pxgtvo_rdWz|QbB4$-eCpNto32t3*)gJ$+aO+AfRO&p@ebO*$d!yJq41~ifiXC(7;1(*crI=DFmjYeXB$R1&)cdun{@Q?P z!CkoAaKc8y;Eo=4@n`g>LtS(v^)#k;3WK&cA-5R=B-Sv3sBp*gX~I*-@vSxSHK)0#mG9Y z2fUDW{g`F~KEMXLJONY;%$vdXBTbmmNoP_WADV9G{66{qFJOq70BuX>)jhxQXmqxJh0Oz7-u=QbnIR=EKLpE9sh=zq>MV}5k@Pa-=ZE0za^Ve1P zcF$8b#~4n9YdWInw^i($&c|WXz$16E%Iv&>KPMNNcld*+MlY4JZmFiB@W9$llFW?o zlNybl0c>$`n4j5NXI*Xcl0oyYW+nr>-dT1>DAqKQ#(l0<)$H7^e;Z!F?#cFuBa$Sn zyxC$$s0={uP?FlmNqB?TygPe!epeL(V5m}qw753`Spn!|klDD*9f^pq9I1Gd6G zSz0=`FmKP5hG6G>&ISZRdm&vrLM7zDnrgyCT~D^UJb}9lVIDSV{*pQ06PJIv9-!%S zXvOOdM<%QYp4Tc7du9UNQnQbbu$RAuU&gwZj0Uj!dy9)8Y}tKG72(BU^xN4Bh-nn! zzTdYt!CQ_I_R6Gnkt74z+d(zg9QG@QW^v^8GJ$aurkdcXr8~E^!M2>`q`gjX?$Pq0i=|)2%Eu7qHSzlcDO0!_mdRxasLYQqVs_AJ)1&#e zXeLPimJd_f-BkqC2vvnhZF$I7+HbBvmIH(x#RGt%0wM~fs1+PKknBBbySaJ_rN9g8 z>G?uipy_Pzz4bMRvEJ|T?67YO^TJ~MvP51yeIgX~ z+|&%4)h3(?#bE&2n$EwME)V-k>Y+4V3k;Ji!x`sdVyZ_(Zo(aqxJ&1Lk>i}H$! z^!I>%0D%7B=_!BnLF>gu&J*2@EI=nz9v|<_P66rz#X%^lMZa$lJ!5?~8D!ovK5?W^ zuVJ-vY4i`RaiGeaPrBK9;k95afN|?IJ>k3F^XJ!lSdRw9k9;z>08z3H6Q7=*zL~Rc zvI50!5QeV;CZ$PZF)eFkKmWTIb9L*n?x)k!)1$|#mfVz0kK+5%#av%4XubvPNPkM0 z@M=c9s7%2S>$|Dd2m|%E=DN~vHaqqX0kttX=|182FE0MuFuk)&@Q0x(VO6) z`)po~8PuT&=X}aclX-H1v~G)Eck3)Jr2{baJrnx7ebbL{GDIHYg>9y!A9`;Ra7LyMXzK!p7h@Nv z$n*?IOH#&phb*}>xHD_!9E#ooZJA#23)Zxun&$vBI{ztrvwMC36om?LUz;_#4(ES~ zn4|>H8g8sk`H{gFs-~4iU)(0f+wszT}86=CIcMY$%_Bx4*f=4v6VYrDZe#T9eg&S+kW# zlcX=YabQXIh?syd`t2w3%=JI%s#}>~?`u66Q;B<<`_rZILh?Xr^&5SEQTiJ|N&Ej^XQ>C+XRHF5St9s}JP zz%Tp(0o4>nit{Y%VFq73U`N3svwKmhloh`w5tk2EDAhz>DeGsA8qRO49@^>;=t7(y zJP;YtHC6w{>7&Y6HFedKb^Y0CkjReXonsj@-nWweMqZd#o2j9EWVRIv$Q9Sm)~Uns z&?VThhLY|D0|sCF|dXv>xJ&jXa--_0G{J!JcX9&viq zQ)sb|2Usg<&=F|+OX*|?fw#y#MzN3IoOB)pTHgL$F|o|NkzL|s-U(JObT+V%Kz_5X z+retTF^=&b@8Y0Ib74HGAsvzvJl^cp2ECxB`}*OMfi>$*bv0l{@WLJ{X+~NZY`Tt% zY}gsSoE_P8-Z`_yQ{*p;8oapT?ZPsb$G=Y1&YCKC9G9TFt&E=IENB8850C-wkiXsv z^&4p91>WPQm(ksp7Dh#a_LmeK27wk9y zXfld$TRy85ThfHe-wwi{p{4ZN{MN`yi;uZJ!9%2Q8{{0`7P};v-gEb4fRMN20{wBy zE^8h$Zzwli_~_fkH4vQl8o#15hItH|^LO>-w2uKkXdX9TrwzGBBTOu6v_q7U)mTMF zP$T!#rMW~r2;C}fIX3o+s-eH=ScpY#vT4XJdHxQIdm0GeEPjsp?#fZe(DC8BXjF+#qg zL@!&EEfNkaU%}UTQns7OQ-&q+?$CRdp~;W6SODRue_EP{O5I7F-YlfJs72w=2>w*Bce%5|E z2VBFt8Xy7O`8OVPcDvmmbFRCY#b>a&U;2xR-pQr4xA!S1LecyV)aU#+S$i=@H&@=? zsgAX+tykNdn}AbibMJk`%rk@ikrZ!ChHb#bkM6Uz^@fIq{Se6}2H5oU7e#z_ zw;pcfYCmvjpQ6+HENR94({HF95r}pH@qpihl(0L<3#`@jhKvO^j1A1FV$&o=|F)6L zohLJef5$m^aO+UUub}8Q6Tk2sWFCmzHi=6AB#UPNl|hd9i#H~6au<#K!f<6q@41o? z=a)zh3B|il9Iq3NhYPA}YvcPYO%J68P@ebw4{mEd(Ol4SnkE;S#{`eWmx?f*b&h&q z5D>Gk#tp14W~BPBtYh4sk?CJPPT^@vuk$@sb|~XpwPy?q^|NKvrhM;Yp&fg9JSjSx zEUOu-4yZJij7Yc%m4fyw;kVXAhhGOqNWuilxR+e}Z@2Qx>jR^(UM9Z#;q0f6p55p2 zk=sl|u(zR*RZs$NjrH?#JVMGi+F4?BZU4r`Oq$7N#}Hy6W6 zE@eTtmvZ-`7+$X4$>iHZJYHmzAzZ9Kg$iEtJ+ij zcr3fPbMi5{fHD9k0ddF3X|l70JYp4KnSht^KNsP~&R8dsW8p=`VDRRr+{}-s3LFx@JkWwLyyVNnam7 z;Lfi}S>RbWnE(x)*AXN28BpmCA7SX9>~E9Zoz*kxc`XUZKyQ$7wa){hp@n|hDZ7ZO zj~W95IRSLlyI-UTu|S6n9H*_+<v!9N>9Z7C)q6JBwCO*2751BH z)Y2oejJdXeL$b`n@_Ho^y{^HEWuMxD+%xPTSwp3}+Aj@00d0-&>IqQsioEUFCT`W-bs&CmWV21b$s;TJbhFK(q}*k0?=>j?@3 zT;YS{^ykY@xoXd(B@zZ)=JnvJw{;~1!+iqg3=L1aehu=wT1HahmLiQxv4@ZVN)`^mm0k}teJZjOPrmPB-E?V4PK5lML zXay(;5O?lu{tQ7p>&q{+1!B*6r*;uu>9E3#G-W0LZtI9#?;Z0VA4w;n*Mcg`tr2p zUUX4hAJ9IRR@$T%#=A0*czJlIDl!k$unhp^9w2SA6RI+R%o5<6d@2*X?1{?YY{1ju z$2H1{6y9XhO!(*(ZwtE9z&>~%VD=XYp@Xl@_11th13=omxq?SK0^ggrXaGc8?(?U% zXz{ZC2!IB6S}cO$2aN99b1(q!n31BW2i8bcCN5oFO`r88KTCp_Mjb;7@45@)m+@2| z+NWZ>--Z7A^kuCtuHu~of7+1M^Y2elOt_Syej~q5+U`m{A8O=6)&-txRPX|}?)JdI zUxL!#8Q}?DWKbkc@CHe0Z!@N%!+(oX{7RAzxmY^i!; z{iKE;2Ner~+;iW5p<~CbjZ~uG8iRKjQw$eOsP($VKj-iv+!5R1GwyTQB;vUJ`q}$P z4;}u}{+}K|nYB&Ns(0rV%=?qO3voy4E#4Ru>~p6`;Yq%PY_yY-C>FELg{Qp@PLQbq zTM$q;Tu+=BRHTQXo?3N=L;}9=or(SBX5hIf{<_inwDs)}A z>c5zQjwW>gqvgcGX29&{guErq9TY?+pC=R}YtBnmRwj_XG}IOgr!+U()NT4caRpe) znphkO0Vc&WEPcYbM*Oe247d&OIGxAo?atWqFo2#s5+eL?H>!l;&H zFR*t&S+Hbi=J`=gua38>&x$n(?R?Pav9 zL-nRtqp0x*>P!cUJ2qN=X@CkI;$nJn$V+oCts(t2fu}aa|UU~F8v~985}Gh&|eGzY0T&QCZkkGKnUN`2guWo zmG*43Iw`v?=C3=4qcH&7Em%4#>rHk=*1cEo=N`^sNE@0a96-$2@naTum)fja(znWL~6u|?4)$ex~(W~!+wNHh@IAaRYK_MkhZgXD_ z$F_EtIBs13S@kjPfyQYJfZK40{C$R+@+W~*eX$r82B@K90$M^U;M4#wax?0n`Y1j! zX_aLbwWZCKpP;};hiq9*sl|-UX&}X~1BQp1ec)LVIYL#rZQ`F+N&~EQB-_?tCfZ+X zwhd@)5gZ&k+Ucyp*eGN(-&P{>Cnb0voHe+&!#u#v#x{63zX}JW1us=VbJl98eGiZw z+dxnQok}`*eMJo*blZ$`zZ~1SwB{$js^2LWg4v_dd%sn6FM47%8711upB0qF0U6I5 zHd0BTi8sB~2()zA!8tunMcoQ!+Q|<5`17;hH1w0&r+6iC%I%4Ul$l7ME9|_KLId)@ z6lD@ghvx2nJpk~Nc>}i2p`nVwR}jGs>_>&CVG`V^76_ETo-~f0?l9M|6~!rREZNmo z|3DpR!5a*SAL?xTn@!7)5M1i7Rd1Ze!M&c)a=NSbGo}q;lOq;^=dD@z+s-whKV`i6 z6?QXxbd#}ea&s}_;qGn>K4!(im+SK$@$2vVH?;hn?Y-@n1H&A3SDbRPU#);1HtVO0 zkd5mnI+w<805f{L(;$BSr#)KS^C`9T^{NSS>G~i#Ab)9mx2(Yl_vROoLv3aIwKou~ zZdbNXM-txHtnV1Z4%U`@I0JgRZ!W}VyF$b_W4F9Xua_U{*=`yi?YGK_cZr|I3_MOA zxLQ#&PE4VTVgmBkhxYdNb!0f2aMVH$7K;M=KZhJ0YGqkF3j{Zxu%GHi_<4B4mO47# z%gEux!Y{z4zJRG?Nr4jzmin(wO*KY&?|k_5F=h~$p^XLvA&}mLfO}sfQwsx)K8p+V zC=P@5hL4^6bn-RZ09Y^hdwRfx9$^J{6@^JPwln zJ$B_=*QAI8PFsCvf`kD5|FW$pm(T?e+T3oINDXXhApu%+;8Pz~R%isM0MS&ys16jf zm`Nv%-Tmeoh@fsVRoeruU~V5r*N=fm0?(-^tCC0ptrfGHE;yJ0F8C$(RgsK8u&u4+ zraYHBOMREF?0e7+!nd7kzpua^r6?DIJ6rB4@6tmaL?osIXLB!V63EkhU>WB>@JIXb z6qQhp%RjO2+{$`cO+Ja`tE)sYY#cq}9!iN{F~ma!bg)VA3qaRdob5kuJ4dIjLk>Mp z8Jq0ezJT27zJ{9>Awl$I8R|1TPNN8SYTu zlnH0u`=bvkRAZplNjq7bd;H3Ji0wVp4&@AH>{$zna>NvgnMlt^Y+YT@s}mUGgJH-)wfr<)b73ktEFQEU83Zn$aAl^vi@3kU&~-kME&K*Gxm1M ze>2|(=i17KP60Z^`nNPQaLR8(1gqRXhHWpeFU(uu(4)i@M`Z%y4wP_BjURFDRzgFD ztnhdEpDfGF-G|cng7}X&vT33Ah{T)1>r}qs$BSPxRZiK#I7_7kBT)?v0tT3vwgf=4 zY}L|)Gk&1y11pv9d0S#*TU&DZcPpnpeew$QcBY z!=~p*BJ!O?7 zlBRc_yHh^Tkd15atpG;=AHPG6(0%W#7!Y_RCz!uBz6C)*r@o!R`Cr1Avu9s&W6py< zY|sOlmyr-S^a;WepeF#wfwDC;?&N(P1@Zf6E!%)NZ`!82VEAEys3uMjbo+?U01pgG zFs<5syPv&dru&Jfz*MIV;lCu3nTaD8u<&4$do3E)t7{JwD8F$)z>e8h=YYXXVluoz zmZ1t3w;Cl-qT)P=P=rG%AQKdC1srP4QR>a`h4xB&2VN>VMGup4)QrkMIcUwuc+j*# zz+$WWa@7=v4kQ!4kE*UB18-FkD=VuS(^3VM+H_CXmpI@^%JZj%jx(sg{ zZ5^9DJ`iP`?+3Ii5wnpi<-y1DO6?@c3Xle5-LeBgbxc7JZ9Td&YmxN;)7Bh-L#+bhCf$Spwh4Q0C^S9o4#<$3`kB2DNnmEf zuNYoO0n7*-v;gNfT+1tVFGwHvXN>?}1RMYnQ(`P-9t3A2z-b9c-)Q2K_W5t+=Ic0d zBj6f1IsuM^{Lp(ozsX~*s3ru4x3I8@s&AiPV7Zf`$p!1)-TYy2T%yJI;0J)C05Icw zdHzCZx2!Do5ZsVun+pjI=Qu zAaP?=#?_Mac4I2fjq5#a6ChTC1a>)gtG{?LLxYYE6+3>ANa)H(phSDAsX6Lv#BS&$P|V;{Bm|Lf1*g4w ze>atu0`f8D7Y^z@?l{JwKUaUD70EofM2z)!!M*82?w%J{P69s9-qXAK2S}1V{?eoI zKq57gLjvt=C~-`q>F#zcq+;;b26N8~>g{blmudO9{56*l;`e!ZxJst={NcIZaKi$Y z4<DgEi8gnfbmvY#7QIlQUff=)sa99S_tyFYU+z_8hiWTXUNB7rR8B@ z8O|Kvw+tjjzuDq3SMfslw-w$7+?U1q3$V~~-P_0hVa@<$hJ7s!)cQ35@D>?SdmBB2 zOaRPl;-mfI(k++f0@UG-uAA7@S(ljpm*>rm3r+ESKc@TpBdkY&AV!a(~_((Qqr0PfAQhZ!hQ6Z=!ByIaMmtTynfzZ0I%l-z{!sM zZ>)Id){*8kxZ|k~vU%aTysj=CU?L*A4}pqkpv&`e#KgbvNMu`0<`f9+u759hu*VDx z9r4tuL` zElCGwsZ|LYg=wpuTTMatdDD5)%W%sVE?W8BY35=M2xV`6514%C>3IQ25M%HcEt)!+ zn;XW!>gWJ}YohN+HB8F-ZO)R*g9lCUWrz+oflwUdiBN{f2>6Q+K!cR0HABR<_@Q#O z{;*s1wYjWDHmNrbEcUyr1W|+L&x_c~wwF9&H^tj;*T)NnKsFJfz0L0Xzv?*ia47q> zkC(`H$B-@iWZWS}NTEr_zGSUo3?h;B&e9BNQHIh@G{nd@H0q|YjU+UcL|KZFWoSX} zEZIY0%3bd{z0dJJ$MHVLGyj=C#&!L!>vx{N^E^M_uYr8!`i2UBOlLEd?9mFySUdlw zX8NxD8oW+CIePLoUE{j?UA%%_rk{E@e=X{Gb5CxP# z4s%}N;ko@%Vk;Q&R0$Zb?=#&ellHtotZm~{FgmA1+?Cm4aY)z|#y2p{{^ttr%Cj+` z!~|tTiTW@Sif)A2`D!=(gzQKuX(|_dQp7H|%*{mYuktyci(pn5lt(<;r^vaRE_kKe`=%{ z#C@}g4}SwzDNoMD@(w4voeJ}tVz%+kbX47Y;;Z7FqYB(&Z{z6?hmlEUNqzBZ7-D+= z`6<`BDvlOtBtYdvd9i8prK3MT#F^fE!n5GXL`{sw8K;*I8%T0)J+5I!o;bewlvfJ< z3u{=Kn0;|=SJJDw+8gjt04c!+s31{=PQM`cT0ZgpI2#dDxvjcBTI-as=srRiLL?cY zgv+eJh8f~j*67XZP_CiRM(4@BA~N#wCy;i%0P!>po8RwjnnwqeF|?90=W+n3vGi&w zdW{bUjRR;BNXYRCvw;lq$|Eh0umPTOYX*zXnf2rAQq8a&1lgi!UR=ln2b~I2SYWhu zH7GmDIi!YJC708gC{5zpLfU14Rb>WaMs%0+f`?j%ht1?hd}vKQUYml5LWE>2zjh3_ zawXbZ3vZXe&~~raBn?|;Z;WV+v0^=k%k)*d^9t#TZ4;~0_mGDNw!2Su1rs&p-d87? zkdip12@&PdbsRph@S)6X!G8b322u%6@K*pwCRAUq4h)!2cM;cCo#GxFMw=&mr%IQw z>g&n*)2%~8S%c;0$~02kn2+Qd%9bx!gz|<;Gc#`EhaRu;yMONWw3*yt2j@>J89QwD z%T7h>GahL|Tsd^n5L?QVAKvqV-9c{rmWd((aQmvsH-2mh)AhmcY+o)K=1D`okT-OK zRmV+CdfC=ov-E|&2xBK4&V+kw{kWdE(D?&^AN<5wyQ&IPhw;rDpepHJ460P?G5CX7 zU0z3nVHTFbZXLqMMnsqtLhlSw0a6=fkz^~^+q67*GDx<}-?o50fMSsAqi*R6qpN$% zKxe+c0v-W-lAbDg+Lt1i7C~PNDTY50X2_*28BV1t4!xk9yW>aMcc}^(DzBF>BNG!_ z31@~ZJU-8{HAH6lWUXB7OIK73GEoWfzi+I!aivM88@*#Abi3$DPC&jsU2sy-+G7%6 ze2+>4@-v0r)53;Qk0)SB=$+ncNm2Yv+JQ_0f*f7{ZaVTaM%<|$jr9xaZ(TpLS0>TZ zCMM`;^KxfCr1#tR4xfy?V*Zr+Cj3hIZ!(f}4}NdP-%~~TU6aAuFG$4jifUgbA!N&^ z(4LRN!;eMzrlO67Omc@D?URLWin@mZxNBt!Vg}GIvBnczj1I@L*GieP5|)M%=0n`- z{DJ$$T4A1Z3-j}zKKYS!ee@%_9$|%CsFs{gsGCtF6~P{BiM#4`7Ut-~G2g*gfpfCs z6zc+*IvI)RtPD&=npFhHZ%tw_UgLkm7;$kgFM$J-l-N)1OWobf4Cdu$#l_oMXJx$f zLJZ^uM7LcPjNkbd;8$!>ctrT2`;(I4+A%-2)5|pMGatjaY3aVj9EqChf;6? zyDc;RmhSyf?jNsrCaQw;PoHtq#gWCJmkviUX)7#-1W4#p)65-(T-==Zmjo-g7=4h} z9AX2k2!LsW`@!Rrs6vN_DVHO`RLZ`5Tv|KCHb(b`6RrMc7niSPtjAU4*zzW+bxk7$ zVWdkM#mT{^)_>sVvV;DNhAXo2%K+hTw1*Xq;cn=tZ%x_a=INPXQqjD%r;bI;Mlsrf zu#(ZvOz7YIaF3VLOvbowf&0?ls;~0lS%e}LjU%p6>dND)ProEy{MwlFq_-~->dd)&Kr1U&pFcFcjCmo%^{vUDq}~>D>SvWcvum_;Z zLAC?1Zm=if_6Wc+V{L~PPMgHhBJOJoxoz(OPY!vMUEUgxIR&BbbTkY275jMyDOKAW z%pGYE!T#l&0A^`L#CQiYIvxGer#$LL7g zY*_b@n6hUzyS^;Eit7H}EQ}lSN<|zX2?Kq$RId6g}=xhuF8d zR4g?bX8b*Ck>KC~wXN8;L}hky+ee~N zk7K$b_T+ifJ;{3s2;lnQYLcPr6y!Uvry^%;3BjE(0PNk2x+u9{L9;N%L=k_TKLq>X zpqo8R9E8YOVAUp5+o9nu=W=WtiUd>0NcT$1uVlbw9)ycqvi5kqVY`cDqpGt*hf`X1{bg)Jn>E2W&b&9(j zq$Jl-o^Ri>0*xII^8t^h?M2RVhKu9=uz^(}W6O*V^Hk@T!K?+YXrnGHm}Q+u1-2OR z{LiH&hOCdkZ2RX=!6cRyMJqaxcoc^V?cl-kfv2>!%NTDLWA?)X*1UwWJ912yy<*@| z?f&>QZ7S%zsT_T#P_4Z=ftd}M+}oqP#mq%xFXcy1e~RM2dx*ghyAED44{M$rE75PQ zHTBI=g*)i{i|7AjBKE`}G|3XCFwj~2KO&$=Lv8}A*PyYz% z(ys>3Ge_L`k(Umr44lbeizgv&=FWM*3v0vI@D(04B3`ffpzbU?W;yKtcY z(%;7eJxh*;`kz+}xViHEHU4UUE|8^g7=`zWJ$*jQUYh6*Ri`2nbbWB@I}-_V3eH4K z^0VWQ4Al$;?C}slnoU8nEX`6H%!3mr=!;U{U>4V!hzsw5gvrGjf*%o_k0-u9iCi9s zZ)|LA0xleM!(@Hup&ehP#j*0&=^D_**(QPPB~AX&@uzqEG=f`}Nti zH1bn!5?dxU&_6ufnWYMWFynV*im>b9QWzm(LpQTmU~4-d@|cl82noAp^@d2Ol~W+e xnD1i83Y+H&Y=R^NeNhlV_$mG?qEG!4+~mJwI@