├── .gitattributes ├── .gitignore ├── Chapter02 ├── channels.rs ├── closure-borrow.rs ├── closure-move.rs ├── collatz.rs ├── custom-errors.rs ├── derive.rs ├── extending-types.rs ├── factorial │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── generic-function-fixed.rs ├── generic-function.rs ├── hello-rust │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── lifetime.rs ├── options.rs ├── ownership-borrow.rs ├── ownership-heap-fixed.rs ├── ownership-heap.rs ├── ownership-mut-borrow.rs ├── ownership-stack.rs ├── panic.rs ├── range.rs ├── syntactic-macro.rs ├── threads.rs ├── traits.rs └── unsafe.rs ├── Chapter03 ├── ip-socket-addr.rs ├── ipnetwork-example │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── lookup-host.rs ├── mio-example │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── pnet-example │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── tcp-client-timeout.rs ├── tcp-client.rs ├── tcp-echo-random │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── tcp-echo-server-random.rs ├── tcp-echo-server.rs ├── trust-dns-example │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── udp-client.rs ├── udp-echo-server.rs └── udp-multicast.rs ├── Chapter04 └── chapter4 │ ├── nom-http │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs │ ├── nom-ipv6 │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs │ ├── pom-string │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs │ ├── serde-basic │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs │ ├── serde-custom │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs │ └── serde-server │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ └── main.rs ├── Chapter05 ├── ftp-example │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── grpc │ ├── Cargo.lock │ ├── Cargo.toml │ ├── build.rs │ ├── foobar.proto │ └── src │ │ ├── bin │ │ ├── client.rs │ │ └── server.rs │ │ ├── foobar.rs │ │ ├── foobar_grpc.rs │ │ └── lib.rs ├── lettre-example │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs └── tftp-example │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ └── main.rs ├── Chapter06 └── ch6 │ ├── hyper-server-faster │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs │ ├── hyper-server │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs │ ├── reqwest-async │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs │ ├── reqwest-example │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs │ ├── rocket-blog │ ├── .gitignore │ ├── .gitkeep │ ├── Cargo.toml │ ├── README.md │ ├── migrations │ │ └── 2017-11-26-143245_posts │ │ │ ├── down.sql │ │ │ └── up.sql │ └── src │ │ ├── db.rs │ │ ├── error.rs │ │ ├── main.rs │ │ ├── models.rs │ │ ├── post.rs │ │ └── schema.rs │ ├── rocket-simple │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs │ └── rocket-templates │ ├── .gitignore │ ├── Cargo.toml │ ├── src │ └── main.rs │ └── templates │ └── webpage.html.tera ├── Chapter07 ├── collatz-client │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── collatz-multiplexed │ ├── .gitignore │ ├── Cargo.toml │ ├── examples │ │ ├── client.rs │ │ └── server.rs │ └── src │ │ └── lib.rs ├── collatz-proto │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── collatz-streaming │ ├── Cargo.toml │ ├── examples │ │ ├── client.rs │ │ └── server.rs │ └── src │ │ └── lib.rs ├── futures-bilock │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── futures-chaining │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── futures-example │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── futures-loop │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── futures-ping-pong │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── streams │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs └── tokio-curl │ ├── .gitignore │ ├── Cargo.toml │ └── src │ └── main.rs ├── Chapter08 ├── key-exchange │ ├── .gitignore │ ├── Cargo.toml │ ├── examples │ │ ├── client.rs │ │ └── server.rs │ └── src │ │ └── lib.rs ├── openssl-example │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── foo.crt │ ├── server.crt │ ├── server.csr │ ├── server.key │ ├── server.key.org │ ├── src │ │ └── main.rs │ └── test.crt ├── rustls-client │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs └── tokio-tls-example │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── cert.pem │ ├── cert.pfx │ ├── key.pem │ └── src │ └── main.rs ├── Chapter09 └── appendix │ ├── bitflags-example │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs │ ├── collatz-generator │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs │ ├── collatz-may │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs │ ├── hyper-async-await │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs │ ├── may-http │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs │ ├── pest-example │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ ├── grammar.pest │ │ └── main.rs │ ├── rayon-parallel │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs │ ├── rayon-search │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs │ └── url-example │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ └── main.rs ├── LICENSE └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | 49 | Cargo.lock 50 | -------------------------------------------------------------------------------- /Chapter02/channels.rs: -------------------------------------------------------------------------------- 1 | use std::thread; 2 | use std::sync::mpsc; 3 | 4 | fn main() { 5 | let rhs = vec![10, 20, 30, 40, 50, 60, 70]; 6 | let lhs = vec![1, 2, 3, 4, 5, 6, 7]; 7 | let (tx, rx) = mpsc::channel(); 8 | 9 | assert_eq!(rhs.len(), lhs.len()); 10 | for i in 1..rhs.len() { 11 | let rhs = rhs.clone(); 12 | let lhs = lhs.clone(); 13 | let tx = tx.clone(); 14 | let handle = thread::spawn(move || { 15 | let s = format!("Thread {} added {} and {}, result {}", i, rhs[i], lhs[i], rhs[i] + lhs[i]); 16 | tx.clone().send(s).unwrap(); 17 | }); 18 | let _ = handle.join().unwrap(); 19 | } 20 | 21 | drop(tx); 22 | for result in rx { 23 | println!("{}", result); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Chapter02/closure-borrow.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | // closure with two parameters 3 | let add = |a, b| a + b; 4 | assert_eq!(add(2, 3), 5); 5 | 6 | // common use cases are on iterators 7 | println!("{:?}", (1..10).filter(|x| x % 2 == 0).collect::>()); 8 | 9 | // using a variable from enclosing scope 10 | let times = 2; 11 | println!("{:?}", (1..10).map(|x| x * times).collect::>()); 12 | } 13 | -------------------------------------------------------------------------------- /Chapter02/closure-move.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let mut times = 2; 3 | { 4 | let mut borrow = |x| times += x; 5 | borrow(5); 6 | } 7 | assert_eq!(times, 7); 8 | 9 | let mut own = move |x| times += x; 10 | own(5); 11 | assert_eq!(times, 7); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Chapter02/collatz.rs: -------------------------------------------------------------------------------- 1 | struct Collatz { 2 | current: u64, 3 | end: u64, 4 | } 5 | 6 | impl Iterator for Collatz { 7 | type Item = u64; 8 | 9 | fn next(&mut self) -> Option { 10 | if self.current % 2 == 0 { 11 | self.current = self.current / 2; 12 | } else { 13 | self.current = 3 * self.current + 1; 14 | } 15 | 16 | if self.current == self.end { 17 | None 18 | } else { 19 | Some(self.current) 20 | } 21 | } 22 | } 23 | 24 | fn collatz(start: u64) -> Collatz { 25 | Collatz { current: start, end: 1u64 } 26 | } 27 | 28 | fn main() { 29 | let input = 10; 30 | 31 | // First 2 items 32 | for n in collatz(input).take(2) { 33 | println!("{}", n); 34 | } 35 | 36 | // Dropping first 2 items 37 | for n in collatz(input).skip(2) { 38 | println!("{}", n); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Chapter02/custom-errors.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | use std::error::Error; 3 | 4 | #[derive(Debug)] 5 | enum OperationsError { 6 | DivideByZeroError, 7 | } 8 | 9 | impl fmt::Display for OperationsError { 10 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 11 | match *self { 12 | OperationsError::DivideByZeroError => f.write_str("Cannot divide by zero"), 13 | } 14 | } 15 | } 16 | 17 | impl Error for OperationsError { 18 | fn description(&self) -> &str { 19 | match *self { 20 | OperationsError::DivideByZeroError => "Cannot divide by zero", 21 | } 22 | } 23 | } 24 | 25 | fn divide(dividend: u32, divisor: u32) -> Result { 26 | if divisor == 0u32 { 27 | Err(OperationsError::DivideByZeroError) 28 | } else { 29 | Ok(dividend / divisor) 30 | } 31 | } 32 | 33 | fn main() { 34 | let result1 = divide(100, 0); 35 | println!("{:?}", result1); 36 | 37 | let result2 = divide(100, 2); 38 | println!("{:?}", result2.unwrap()); 39 | } 40 | -------------------------------------------------------------------------------- /Chapter02/derive.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | use std::fmt::Display; 3 | 4 | #[derive(Debug, Hash)] 5 | struct Point { 6 | x: T, 7 | y: T, 8 | } 9 | 10 | impl fmt::Display for Point where T: Display { 11 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 12 | write!(f, "({}, {})", self.x, self.y) 13 | } 14 | } 15 | 16 | fn main() { 17 | let p: Point = Point { x: 4u32, y: 2u32 }; 18 | 19 | // uses Display 20 | println!("{}", p); 21 | 22 | // uses Debug 23 | println!("{:?}", p); 24 | } 25 | -------------------------------------------------------------------------------- /Chapter02/extending-types.rs: -------------------------------------------------------------------------------- 1 | trait Sawtooth { 2 | fn sawtooth(&self) -> Self; 3 | } 4 | 5 | impl Sawtooth for f64 { 6 | fn sawtooth(&self) -> f64 { 7 | self - self.floor() 8 | } 9 | } 10 | 11 | fn main() { 12 | println!("{}", 2.34f64.sawtooth()); 13 | } 14 | -------------------------------------------------------------------------------- /Chapter02/factorial/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | **/*.rs.bk 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /Chapter02/factorial/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "factorial" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /Chapter02/factorial/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[allow(unused_macros)] 2 | 3 | /// The factorial crate provides a macro to compute factorial of a given 4 | /// integer 5 | /// # Examples 6 | /// 7 | /// ``` 8 | /// # #[macro_use] extern crate factorial; 9 | /// # fn main() { 10 | /// assert_eq!(factorial!(0), 1); 11 | /// assert_eq!(factorial!(6), 720); 12 | /// # } 13 | /// ``` 14 | #[macro_export] 15 | macro_rules! factorial { 16 | ($x:expr) => { 17 | { 18 | let mut result = 1; 19 | for i in 1..($x+1) { 20 | result = result * i; 21 | } 22 | result 23 | } 24 | }; 25 | } 26 | 27 | #[cfg(test)] 28 | mod tests { 29 | #[test] 30 | fn test_factorial() { 31 | assert_eq!(factorial!(5), 120); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Chapter02/generic-function-fixed.rs: -------------------------------------------------------------------------------- 1 | use std::ops::Add; 2 | 3 | struct Tuple { 4 | first: T, 5 | second: T, 6 | } 7 | 8 | fn main() { 9 | let tuple_u32: Tuple = Tuple {first: 4u32, second: 2u32 }; 10 | let tuple_u64: Tuple = Tuple {first: 5u64, second: 6u64 }; 11 | println!("{}", sum(tuple_u32)); 12 | println!("{}", sum(tuple_u64)); 13 | 14 | let tuple: Tuple = Tuple {first: "One".to_owned(), second: "Two".to_owned() }; 15 | println!("{}", sum(tuple)); 16 | } 17 | 18 | fn sum>(tuple: Tuple) -> T 19 | { 20 | tuple.first + tuple.second 21 | } 22 | -------------------------------------------------------------------------------- /Chapter02/generic-function.rs: -------------------------------------------------------------------------------- 1 | struct Tuple { 2 | first: T, 3 | second: T, 4 | } 5 | 6 | fn main() { 7 | let tuple_u32: Tuple = Tuple {first: 4u32, second: 2u32 }; 8 | let tuple_u64: Tuple = Tuple {first: 5u64, second: 6u64 }; 9 | println!("{}", sum(tuple_u32)); 10 | println!("{}", sum(tuple_u64)); 11 | 12 | let tuple: Tuple = Tuple {first: "One".to_owned(), second: "Two".to_owned() }; 13 | println!("{}", sum(tuple)); 14 | } 15 | 16 | fn sum(tuple: Tuple) -> T 17 | { 18 | tuple.first + tuple.second 19 | } 20 | -------------------------------------------------------------------------------- /Chapter02/hello-rust/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter02/hello-rust/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "hello-rust" 3 | version = "0.1.0" 4 | dependencies = [ 5 | "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 6 | ] 7 | 8 | [[package]] 9 | name = "kernel32-sys" 10 | version = "0.2.2" 11 | source = "registry+https://github.com/rust-lang/crates.io-index" 12 | dependencies = [ 13 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 14 | "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 15 | ] 16 | 17 | [[package]] 18 | name = "term" 19 | version = "0.4.6" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | dependencies = [ 22 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 23 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 24 | ] 25 | 26 | [[package]] 27 | name = "winapi" 28 | version = "0.2.8" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | 31 | [[package]] 32 | name = "winapi-build" 33 | version = "0.1.1" 34 | source = "registry+https://github.com/rust-lang/crates.io-index" 35 | 36 | [metadata] 37 | "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" 38 | "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" 39 | "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" 40 | "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" 41 | -------------------------------------------------------------------------------- /Chapter02/hello-rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hello-rust" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | term = "0.4.6" 8 | -------------------------------------------------------------------------------- /Chapter02/hello-rust/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate term; 2 | 3 | fn main() { 4 | let mut t = term::stdout().unwrap(); 5 | t.fg(term::color::GREEN).unwrap(); 6 | write!(t, "hello, ").unwrap(); 7 | 8 | t.fg(term::color::RED).unwrap(); 9 | writeln!(t, "world!").unwrap(); 10 | 11 | t.reset().unwrap(); 12 | } 13 | -------------------------------------------------------------------------------- /Chapter02/lifetime.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let v1 = vec![1, 2, 3, 4, 5]; 3 | let v2 = vec![1, 2]; 4 | 5 | println!("{:?}", longer_vector(&v1, &v2)); 6 | } 7 | 8 | fn longer_vector<'a>(x: &'a[i32], y: &'a[i32]) -> &'a[i32] { 9 | if x.len() > y.len() { x } else {y } 10 | } 11 | -------------------------------------------------------------------------------- /Chapter02/options.rs: -------------------------------------------------------------------------------- 1 | fn divide(dividend: u32, divisor: u32) -> Option { 2 | if divisor == 0u32 { 3 | None 4 | } else { 5 | Some(dividend / divisor) 6 | } 7 | } 8 | 9 | fn main() { 10 | let result1 = divide(100, 0); 11 | 12 | match result1 { 13 | None => println!("Error occurred"), 14 | Some(result) => println!("The result is {}", result), 15 | } 16 | 17 | let result2 = divide(100, 2); 18 | println!("{:?}", result2.unwrap()); 19 | } 20 | -------------------------------------------------------------------------------- /Chapter02/ownership-borrow.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let s = String::from("Test"); 3 | heap_example(&s); 4 | } 5 | 6 | fn heap_example(input: &String) { 7 | let mystr = input; 8 | let _otherstr = mystr; 9 | println!("{}", mystr); 10 | } 11 | -------------------------------------------------------------------------------- /Chapter02/ownership-heap-fixed.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let s = String::from("Test"); 3 | heap_example(s); 4 | } 5 | 6 | fn heap_example(input: String) { 7 | let mystr = input; 8 | let _otherstr = mystr.clone(); 9 | println!("{}", mystr); 10 | } 11 | -------------------------------------------------------------------------------- /Chapter02/ownership-heap.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let s = String::from("Test"); 3 | heap_example(s); 4 | } 5 | 6 | fn heap_example(input: String) { 7 | let mystr = input; 8 | let _otherstr = mystr; 9 | println!("{}", mystr); 10 | } 11 | -------------------------------------------------------------------------------- /Chapter02/ownership-mut-borrow.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let mut s = String::from("Test"); 3 | heap_example(&mut s); 4 | } 5 | 6 | fn heap_example(input: &mut String) { 7 | let mystr = input; 8 | let _otherstr = mystr; 9 | println!("{}", mystr); 10 | } 11 | -------------------------------------------------------------------------------- /Chapter02/ownership-stack.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let i = 42; 3 | stack_example(i); 4 | } 5 | 6 | fn stack_example(input: i32) { 7 | let x = input; 8 | let _y = x; 9 | println!("{}", x); 10 | } 11 | -------------------------------------------------------------------------------- /Chapter02/panic.rs: -------------------------------------------------------------------------------- 1 | fn parse_int(s: String) -> u64 { 2 | return s.parse::().expect("Could not parse as integer") 3 | } 4 | 5 | fn main() { 6 | // works fine 7 | let _ = parse_int("1".to_owned()); 8 | 9 | // panics 10 | let _ = parse_int("abcd".to_owned()); 11 | } 12 | -------------------------------------------------------------------------------- /Chapter02/range.rs: -------------------------------------------------------------------------------- 1 | #![feature(inclusive_range_syntax)] 2 | 3 | fn main() { 4 | let numbers = 1..5; 5 | for number in numbers { 6 | println!("{}", number); 7 | } 8 | println!("------------------"); 9 | let inclusive = 1..=5; 10 | for number in inclusive { 11 | println!("{}", number); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Chapter02/syntactic-macro.rs: -------------------------------------------------------------------------------- 1 | #![feature(trace_macros)] 2 | trace_macros!(true); 3 | 4 | macro_rules! factorial { 5 | ($x:expr) => { 6 | { 7 | let mut result = 1; 8 | for i in 1..($x+1) { 9 | result = result * i; 10 | } 11 | result 12 | } 13 | }; 14 | } 15 | 16 | fn main() { 17 | let arg = std::env::args().nth(1).expect("Please provide only one argument"); 18 | println!("{:?}", factorial!(arg.parse::().expect("Could not parse to an integer"))); 19 | } 20 | -------------------------------------------------------------------------------- /Chapter02/threads.rs: -------------------------------------------------------------------------------- 1 | use std::thread; 2 | 3 | fn main() { 4 | for i in 1..10 { 5 | let handle = thread::spawn(move || { 6 | println!("Hello from thread number {}", i); 7 | }); 8 | let _ = handle.join(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Chapter02/traits.rs: -------------------------------------------------------------------------------- 1 | trait Max { 2 | fn max(&self) -> T; 3 | } 4 | 5 | struct ThreeTuple { 6 | first: T, 7 | second: T, 8 | third: T, 9 | } 10 | 11 | impl Max for ThreeTuple { 12 | fn max(&self) -> T { 13 | if self.first >= self.second && self.first >= self.third { 14 | self.first 15 | } else if self.second >= self.first && self.second >= self.third { 16 | self.second 17 | } else { 18 | self.third 19 | } 20 | } 21 | } 22 | 23 | struct TwoTuple { 24 | first: T, 25 | second: T, 26 | } 27 | 28 | impl Max for TwoTuple { 29 | fn max(&self) -> T { 30 | if self.first >= self.second { 31 | self.first 32 | } else { 33 | self.second 34 | } 35 | } 36 | } 37 | 38 | fn main() { 39 | let two_tuple: TwoTuple = TwoTuple { 40 | first: 4u32, 41 | second: 2u32, 42 | }; 43 | let three_tuple: ThreeTuple = ThreeTuple { 44 | first: 6u64, 45 | second: 5u64, 46 | third: 10u64, 47 | }; 48 | 49 | println!("{}", two_tuple.max()); 50 | println!("{}", three_tuple.max()); 51 | } 52 | -------------------------------------------------------------------------------- /Chapter02/unsafe.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let num: u32 = 42; 3 | let p: *const u32 = # 4 | 5 | unsafe { 6 | assert_eq!(*p, num); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Chapter03/ip-socket-addr.rs: -------------------------------------------------------------------------------- 1 | #![feature(ip)] 2 | 3 | use std::net::{IpAddr, SocketAddr}; 4 | 5 | fn main() { 6 | let local: IpAddr = "127.0.0.1".parse().unwrap(); 7 | assert!(local.is_loopback()); 8 | 9 | let global: IpAddr = IpAddr::from([0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1]); 10 | assert!(global.is_global()); 11 | 12 | let local_sa: SocketAddr = "127.0.0.1:80".parse().unwrap(); 13 | assert!(local_sa.is_ipv4()); 14 | 15 | let global_sa = SocketAddr::new(global, 80u16); 16 | assert!(global_sa.is_ipv6()); 17 | } 18 | -------------------------------------------------------------------------------- /Chapter03/ipnetwork-example/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | **/*.rs.bk 3 | -------------------------------------------------------------------------------- /Chapter03/ipnetwork-example/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "ipnetwork" 3 | version = "0.12.7" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | 6 | [[package]] 7 | name = "ipnetwork-example" 8 | version = "0.1.0" 9 | dependencies = [ 10 | "ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)", 11 | ] 12 | 13 | [metadata] 14 | "checksum ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)" = "2134e210e2a024b5684f90e1556d5f71a1ce7f8b12e9ac9924c67fb36f63b336" 15 | -------------------------------------------------------------------------------- /Chapter03/ipnetwork-example/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ipnetwork-example" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | ipnetwork = "0.12.7" 8 | -------------------------------------------------------------------------------- /Chapter03/ipnetwork-example/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate ipnetwork; 2 | 3 | use std::net::Ipv4Addr; 4 | use ipnetwork::{IpNetwork, Ipv4Network, Ipv6Network}; 5 | 6 | fn main() { 7 | let net = IpNetwork::new("192.168.122.0".parse().unwrap(), 22).expect("Could not construct a network"); 8 | let str_net: IpNetwork = "192.168.122.0/22".parse().unwrap(); 9 | 10 | assert!(net == str_net); 11 | assert!(net.is_ipv4()); 12 | 13 | let net4: Ipv4Network = "192.168.121.0/22".parse().unwrap(); 14 | assert!(net4.size() == 2u64.pow(32 - 22)); 15 | assert!(net4.contains(Ipv4Addr::new(192, 168, 121, 3))); 16 | 17 | let _net6: Ipv6Network = "2001:db8::0/96".parse().unwrap(); 18 | for addr in net4.iter().take(10) { 19 | println!("{}", addr); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Chapter03/lookup-host.rs: -------------------------------------------------------------------------------- 1 | #![feature(lookup_host)] 2 | 3 | use std::env; 4 | use std::net::lookup_host; 5 | 6 | fn main() { 7 | let args: Vec<_> = env::args().collect(); 8 | if args.len() != 2 { 9 | eprintln!("Please provide only one host name"); 10 | std::process::exit(1); 11 | } else { 12 | let addresses = lookup_host(&args[1]).unwrap(); 13 | for address in addresses { 14 | println!("{}", address.ip()); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter03/mio-example/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | **/*.rs.bk 3 | -------------------------------------------------------------------------------- /Chapter03/mio-example/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "bitflags" 3 | version = "0.7.0" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | 6 | [[package]] 7 | name = "cfg-if" 8 | version = "0.1.2" 9 | source = "registry+https://github.com/rust-lang/crates.io-index" 10 | 11 | [[package]] 12 | name = "fuchsia-zircon" 13 | version = "0.2.1" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | dependencies = [ 16 | "fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 17 | ] 18 | 19 | [[package]] 20 | name = "fuchsia-zircon-sys" 21 | version = "0.2.0" 22 | source = "registry+https://github.com/rust-lang/crates.io-index" 23 | dependencies = [ 24 | "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 25 | ] 26 | 27 | [[package]] 28 | name = "iovec" 29 | version = "0.1.1" 30 | source = "registry+https://github.com/rust-lang/crates.io-index" 31 | dependencies = [ 32 | "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", 33 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 34 | ] 35 | 36 | [[package]] 37 | name = "kernel32-sys" 38 | version = "0.2.2" 39 | source = "registry+https://github.com/rust-lang/crates.io-index" 40 | dependencies = [ 41 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 42 | "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 43 | ] 44 | 45 | [[package]] 46 | name = "lazycell" 47 | version = "0.5.1" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | 50 | [[package]] 51 | name = "libc" 52 | version = "0.2.33" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | 55 | [[package]] 56 | name = "log" 57 | version = "0.3.8" 58 | source = "registry+https://github.com/rust-lang/crates.io-index" 59 | 60 | [[package]] 61 | name = "mio" 62 | version = "0.6.11" 63 | source = "registry+https://github.com/rust-lang/crates.io-index" 64 | dependencies = [ 65 | "fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 66 | "fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 67 | "iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 68 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 69 | "lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 70 | "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", 71 | "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 72 | "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 73 | "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", 74 | "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 75 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 76 | ] 77 | 78 | [[package]] 79 | name = "mio-example" 80 | version = "0.1.0" 81 | dependencies = [ 82 | "mio 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", 83 | ] 84 | 85 | [[package]] 86 | name = "miow" 87 | version = "0.2.1" 88 | source = "registry+https://github.com/rust-lang/crates.io-index" 89 | dependencies = [ 90 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 91 | "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", 92 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 93 | "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 94 | ] 95 | 96 | [[package]] 97 | name = "net2" 98 | version = "0.2.31" 99 | source = "registry+https://github.com/rust-lang/crates.io-index" 100 | dependencies = [ 101 | "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 102 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 103 | "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", 104 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 105 | "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 106 | ] 107 | 108 | [[package]] 109 | name = "slab" 110 | version = "0.3.0" 111 | source = "registry+https://github.com/rust-lang/crates.io-index" 112 | 113 | [[package]] 114 | name = "winapi" 115 | version = "0.2.8" 116 | source = "registry+https://github.com/rust-lang/crates.io-index" 117 | 118 | [[package]] 119 | name = "winapi-build" 120 | version = "0.1.1" 121 | source = "registry+https://github.com/rust-lang/crates.io-index" 122 | 123 | [[package]] 124 | name = "ws2_32-sys" 125 | version = "0.2.1" 126 | source = "registry+https://github.com/rust-lang/crates.io-index" 127 | dependencies = [ 128 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 129 | "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 130 | ] 131 | 132 | [metadata] 133 | "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" 134 | "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" 135 | "checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159" 136 | "checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82" 137 | "checksum iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6e8b9c2247fcf6c6a1151f1156932be5606c9fd6f55a2d7f9fc1cb29386b2f7" 138 | "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" 139 | "checksum lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b585b7a6811fb03aa10e74b278a0f00f8dd9b45dc681f148bb29fa5cb61859b" 140 | "checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2" 141 | "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" 142 | "checksum mio 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0e8411968194c7b139e9105bc4ae7db0bae232af087147e72f0616ebf5fdb9cb" 143 | "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" 144 | "checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09" 145 | "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" 146 | "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" 147 | "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" 148 | "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" 149 | -------------------------------------------------------------------------------- /Chapter03/mio-example/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mio-example" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | mio = "0.6.11" 8 | -------------------------------------------------------------------------------- /Chapter03/mio-example/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate mio; 2 | 3 | use mio::*; 4 | use mio::tcp::{TcpListener}; 5 | 6 | use std::net::SocketAddr; 7 | use std::env; 8 | 9 | const SERVER: Token = Token(0); 10 | 11 | struct TCPServer { 12 | address: SocketAddr, 13 | } 14 | 15 | impl TCPServer { 16 | fn new(port: u32) -> Self { 17 | let address = format!("0.0.0.0:{}", port) 18 | .parse::().unwrap(); 19 | 20 | TCPServer { 21 | address, 22 | } 23 | } 24 | 25 | fn run(&mut self) { 26 | let server = TcpListener::bind(&self.address) 27 | .expect("Could not bind to port"); 28 | let poll = Poll::new().unwrap(); 29 | poll.register(&server, SERVER, Ready::readable(), PollOpt::edge()).unwrap(); 30 | 31 | let mut events = Events::with_capacity(1024); 32 | loop { 33 | poll.poll(&mut events, None).unwrap(); 34 | 35 | for event in events.iter() { 36 | match event.token() { 37 | SERVER => { 38 | let (_stream, remote) = server.accept().unwrap(); 39 | println!("Connection from {}", remote); 40 | } 41 | _ => { 42 | unreachable!(); 43 | } 44 | } 45 | } 46 | } 47 | } 48 | } 49 | 50 | fn main() { 51 | let args: Vec = env::args().collect(); 52 | if args.len() != 2 { 53 | eprintln!("Please provide only one port number as argument"); 54 | std::process::exit(1); 55 | } 56 | let mut server = TCPServer::new(args[1].parse::().expect("Could not parse as u32")); 57 | server.run(); 58 | } 59 | -------------------------------------------------------------------------------- /Chapter03/pnet-example/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | **/*.rs.bk 3 | -------------------------------------------------------------------------------- /Chapter03/pnet-example/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pnet-example" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | pnet = "0.20.0" 8 | -------------------------------------------------------------------------------- /Chapter03/pnet-example/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate pnet; 2 | 3 | use pnet::datalink::{self, NetworkInterface}; 4 | use pnet::datalink::Channel::Ethernet; 5 | use pnet::packet::ethernet::{EtherTypes, EthernetPacket}; 6 | use pnet::packet::ipv4::Ipv4Packet; 7 | use pnet::packet::tcp::TcpPacket; 8 | use pnet::packet::ip::IpNextHeaderProtocols; 9 | use pnet::packet::Packet; 10 | 11 | use std::env; 12 | 13 | fn handle_packet(ethernet: &EthernetPacket) { 14 | match ethernet.get_ethertype() { 15 | EtherTypes::Ipv4 => { 16 | let header = Ipv4Packet::new(ethernet.payload()); 17 | if let Some(header) = header { 18 | match header.get_next_level_protocol() { 19 | IpNextHeaderProtocols::Tcp => { 20 | let tcp = TcpPacket::new(header.payload()); 21 | if let Some(tcp) = tcp { 22 | println!( 23 | "Got a TCP packet {}:{} to {}:{}", 24 | header.get_source(), 25 | tcp.get_source(), 26 | header.get_destination(), 27 | tcp.get_destination() 28 | ); 29 | } 30 | } 31 | _ => println!("Ignoring non TCP packet"), 32 | } 33 | } 34 | } 35 | _ => println!("Ignoring non IPv4 packet"), 36 | } 37 | } 38 | 39 | fn main() { 40 | let interface_name = env::args().nth(1).unwrap(); 41 | 42 | let interfaces = datalink::interfaces(); 43 | let interface = interfaces 44 | .into_iter() 45 | .filter(|iface: &NetworkInterface| iface.name == interface_name) 46 | .next() 47 | .expect("Error getting interface"); 48 | 49 | let (_tx, mut rx) = match datalink::channel(&interface, Default::default()) { 50 | Ok(Ethernet(tx, rx)) => (tx, rx), 51 | Ok(_) => panic!("Unhandled channel type"), 52 | Err(e) => { 53 | panic!( 54 | "An error occurred when creating the datalink channel: {}", 55 | e 56 | ) 57 | } 58 | }; 59 | 60 | loop { 61 | match rx.next() { 62 | Ok(packet) => { 63 | let packet = EthernetPacket::new(packet).unwrap(); 64 | handle_packet(&packet); 65 | } 66 | Err(e) => { 67 | panic!("An error occurred while reading: {}", e); 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Chapter03/tcp-client-timeout.rs: -------------------------------------------------------------------------------- 1 | use std::net::TcpStream; 2 | use std::str; 3 | use std::io::{self, BufRead, BufReader, Write}; 4 | use std::time::Duration; 5 | use std::net::SocketAddr; 6 | 7 | fn main() { 8 | let remote: SocketAddr = "127.0.0.1:8888".parse().unwrap(); 9 | let mut stream = TcpStream::connect_timeout(&remote, Duration::from_secs(1)).expect("Could not connect to server"); 10 | stream.set_read_timeout(Some(Duration::from_secs(3))).expect("Could not set a read timeout"); 11 | loop { 12 | let mut input = String::new(); 13 | let mut buffer: Vec = Vec::new(); 14 | io::stdin().read_line(&mut input).expect("Failed to read from stdin"); 15 | stream.write(input.as_bytes()).expect("Failed to write to server"); 16 | 17 | let mut reader = BufReader::new(&stream); 18 | 19 | reader.read_until(b'\n', &mut buffer).expect("Could not read into buffer"); 20 | print!("{}", str::from_utf8(&buffer).expect("Could not write buffer as string")); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Chapter03/tcp-client.rs: -------------------------------------------------------------------------------- 1 | use std::net::TcpStream; 2 | use std::str; 3 | use std::io::{self, BufRead, BufReader, Write}; 4 | 5 | fn main() { 6 | let mut stream = TcpStream::connect("127.0.0.1:8888").expect("Could not connect to server"); 7 | loop { 8 | let mut input = String::new(); 9 | let mut buffer: Vec = Vec::new(); 10 | io::stdin().read_line(&mut input).expect("Failed to read from stdin"); 11 | stream.write(input.as_bytes()).expect("Failed to write to server"); 12 | 13 | let mut reader = BufReader::new(&stream); 14 | 15 | reader.read_until(b'\n', &mut buffer).expect("Could not read into buffer"); 16 | print!("{}", str::from_utf8(&buffer).expect("Could not write buffer as string")); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter03/tcp-echo-random/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | **/*.rs.bk 3 | -------------------------------------------------------------------------------- /Chapter03/tcp-echo-random/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tcp-echo-random" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | rand = "0.3.17" 8 | -------------------------------------------------------------------------------- /Chapter03/tcp-echo-random/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate rand; 2 | 3 | use std::net::{TcpListener, TcpStream}; 4 | use std::thread; 5 | use rand::{thread_rng, Rng}; 6 | use std::time::Duration; 7 | use std::io::{Read, Write, Error}; 8 | 9 | fn handle_client(mut stream: TcpStream) -> Result<(), Error> { 10 | let mut buf = [0; 512]; 11 | loop { 12 | let bytes_read = stream.read(&mut buf)?; 13 | if bytes_read == 0 { 14 | return Ok(()); 15 | } 16 | let sleep = Duration::from_secs(*thread_rng().choose(&[0, 1, 2, 3, 4, 5]).unwrap()); 17 | println!("Sleeping for {:?} before replying", sleep); 18 | std::thread::sleep(sleep); 19 | stream.write(&buf[..bytes_read])?; 20 | } 21 | } 22 | 23 | fn main() { 24 | let listener = TcpListener::bind("127.0.0.1:8888").expect("Could not bind"); 25 | for stream in listener.incoming() { 26 | match stream { 27 | Err(e) => eprintln!("failed: {}", e), 28 | Ok(stream) => { 29 | thread::spawn(move || { 30 | handle_client(stream).unwrap_or_else(|error| eprintln!("{:?}", error)); 31 | }); 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Chapter03/tcp-echo-server-random.rs: -------------------------------------------------------------------------------- 1 | use std::net::{TcpListener, TcpStream}; 2 | use std::thread; 3 | use std::rand::thread_rng; 4 | 5 | use std::io::{Read, Write, Error}; 6 | 7 | fn flip() -> bool { 8 | let choices = [true, false]; 9 | let mut rng = thread_rng(); 10 | rng.choose(&choices).ok() 11 | } 12 | 13 | fn handle_client(mut stream: TcpStream) -> Result<(), Error> { 14 | println!("Incoming connection from: {}", stream.peer_addr()?); 15 | let mut buf = [0; 512]; 16 | loop { 17 | let bytes_read = stream.read(&mut buf)?; 18 | if bytes_read == 0 { return Ok(()) } 19 | stream.write(&buf[..bytes_read])?; 20 | } 21 | } 22 | 23 | fn main() { 24 | let listener = TcpListener::bind("127.0.0.1:8888").expect("Could not bind"); 25 | for stream in listener.incoming() { 26 | match stream { 27 | Err(e) => { eprintln!("failed: {}", e) } 28 | Ok(stream) => { 29 | thread::spawn(move || { 30 | handle_client(stream).unwrap_or_else(|error| eprintln!("{:?}", error)); 31 | }); 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Chapter03/tcp-echo-server.rs: -------------------------------------------------------------------------------- 1 | use std::net::{TcpListener, TcpStream}; 2 | use std::thread; 3 | use std::io::{Read, Write, Error}; 4 | 5 | fn handle_client(mut stream: TcpStream) -> Result<(), Error> { 6 | println!("Incoming connection from: {}", stream.peer_addr()?); 7 | let mut buf = [0; 512]; 8 | loop { 9 | let bytes_read = stream.read(&mut buf)?; 10 | if bytes_read == 0 { return Ok(()) } 11 | stream.write(&buf[..bytes_read])?; 12 | } 13 | } 14 | 15 | fn main() { 16 | let listener = TcpListener::bind("0.0.0.0:8888").expect("Could not bind"); 17 | for stream in listener.incoming() { 18 | match stream { 19 | Err(e) => { eprintln!("failed: {}", e) } 20 | Ok(stream) => { 21 | thread::spawn(move || { 22 | handle_client(stream).unwrap_or_else(|error| eprintln!("{:?}", error)); 23 | }); 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Chapter03/trust-dns-example/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | **/*.rs.bk 3 | -------------------------------------------------------------------------------- /Chapter03/trust-dns-example/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "trust-dns-example" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | trust-dns-resolver = "0.6.0" 8 | trust-dns = "0.12.0" 9 | -------------------------------------------------------------------------------- /Chapter03/trust-dns-example/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate trust_dns_resolver; 2 | extern crate trust_dns; 3 | 4 | use std::env; 5 | 6 | use trust_dns_resolver::Resolver; 7 | use trust_dns_resolver::config::*; 8 | 9 | use trust_dns::rr::record_type::RecordType; 10 | 11 | fn main() { 12 | let args: Vec = env::args().collect(); 13 | if args.len() != 2 { 14 | eprintln!("Please provide a name to query"); 15 | std::process::exit(1); 16 | } 17 | let resolver = Resolver::new(ResolverConfig::default(), ResolverOpts::default()).unwrap(); 18 | 19 | let query = format!("{}.", args[1]); 20 | let response = resolver.lookup_ip(query.as_str()); 21 | println!("Using the synchronous resolver"); 22 | for ans in response.iter() { 23 | println!("{:?}", ans); 24 | } 25 | 26 | println!("Using the system resolver"); 27 | let system_resolver = Resolver::from_system_conf().unwrap(); 28 | let system_response = system_resolver.lookup_ip(query.as_str()); 29 | for ans in system_response.iter() { 30 | println!("{:?}", ans); 31 | } 32 | 33 | let ns = resolver.lookup(query.as_str(), RecordType::NS); 34 | println!("NS records using the synchronous resolver"); 35 | for ans in ns.iter() { 36 | println!("{:?}", ans); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter03/udp-client.rs: -------------------------------------------------------------------------------- 1 | use std::net::UdpSocket; 2 | use std::{str,io}; 3 | 4 | fn main() { 5 | let socket = UdpSocket::bind("127.0.0.1:8000").expect("Could not bind client socket"); 6 | socket.connect("127.0.0.1:8888").expect("Could not connect to server"); 7 | loop { 8 | let mut input = String::new(); 9 | let mut buffer = [0u8; 1500]; 10 | io::stdin().read_line(&mut input).expect("Failed to read from stdin"); 11 | socket.send(input.as_bytes()).expect("Failed to write to server"); 12 | 13 | socket.recv_from(&mut buffer).expect("Could not read into buffer"); 14 | print!("{}", str::from_utf8(&buffer).expect("Could not write buffer as string")); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter03/udp-echo-server.rs: -------------------------------------------------------------------------------- 1 | use std::thread; 2 | use std::net::UdpSocket; 3 | 4 | fn main() { 5 | 6 | let socket = UdpSocket::bind("0.0.0.0:8888").expect("Could not bind socket"); 7 | 8 | loop { 9 | let mut buf = [0u8; 1500]; 10 | let sock = socket.try_clone().expect("Failed to clone socket"); 11 | match socket.recv_from(&mut buf) { 12 | Ok((_, src)) => { 13 | thread::spawn(move || { 14 | println!("Handling connection from {}", src); 15 | sock.send_to(&buf, &src).expect("Failed to send a response"); 16 | }); 17 | }, 18 | Err(e) => { 19 | eprintln!("couldn't recieve a datagram: {}", e); 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Chapter03/udp-multicast.rs: -------------------------------------------------------------------------------- 1 | use std::{env, str}; 2 | use std::net::{UdpSocket, Ipv4Addr}; 3 | 4 | fn main() { 5 | let mcast_group: Ipv4Addr = "239.0.0.1".parse().unwrap(); 6 | let port: u16 = 6000; 7 | let any = "0.0.0.0".parse().unwrap(); 8 | let mut buffer = [0u8; 1600]; 9 | if env::args().count() > 1 { 10 | let socket = UdpSocket::bind((any, port)).expect("Could not bind client socket"); 11 | socket.join_multicast_v4(&mcast_group, &any).expect("Could not join multicast group"); 12 | socket.recv_from(&mut buffer).expect("Failed to write to server"); 13 | print!("{}", str::from_utf8(&buffer).expect("Could not write buffer as string")); 14 | } else { 15 | let socket = UdpSocket::bind((any, 0)).expect("Could not bind socket"); 16 | socket.send_to("Hello world!".as_bytes(), &(mcast_group, port)).expect("Failed to write data"); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter04/chapter4/nom-http/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter04/chapter4/nom-http/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "compiler_error" 3 | version = "0.1.1" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | 6 | [[package]] 7 | name = "libc" 8 | version = "0.2.33" 9 | source = "registry+https://github.com/rust-lang/crates.io-index" 10 | 11 | [[package]] 12 | name = "memchr" 13 | version = "1.0.2" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | dependencies = [ 16 | "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", 17 | ] 18 | 19 | [[package]] 20 | name = "nom" 21 | version = "3.2.1" 22 | source = "registry+https://github.com/rust-lang/crates.io-index" 23 | dependencies = [ 24 | "compiler_error 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 25 | "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 26 | ] 27 | 28 | [[package]] 29 | name = "nom-http" 30 | version = "0.1.0" 31 | dependencies = [ 32 | "nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 33 | ] 34 | 35 | [metadata] 36 | "checksum compiler_error 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ef975f6d3622b15ea669c8075fefa5a9bc4bfae1b8b221ab9962daff003b3047" 37 | "checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2" 38 | "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" 39 | "checksum nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b" 40 | -------------------------------------------------------------------------------- /Chapter04/chapter4/nom-http/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "nom-http" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies.nom] 7 | version = "3.2.1" 8 | features = ["verbose-errors", "nightly"] 9 | -------------------------------------------------------------------------------- /Chapter04/chapter4/nom-http/src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate nom; 3 | 4 | use std::str; 5 | use nom::{ErrorKind, IResult}; 6 | 7 | #[derive(Debug)] 8 | enum Method { 9 | GET, 10 | POST, 11 | } 12 | 13 | #[derive(Debug)] 14 | struct Request { 15 | method: Method, 16 | url: String, 17 | version: String, 18 | } 19 | 20 | named!(parse_method<&[u8], Method>, 21 | return_error!(ErrorKind::Custom(128), alt!(map!(tag!("GET"), |_| Method::GET) | map!(tag!("POST"), |_| Method::POST)))); 22 | 23 | named!(parse_request<&[u8], Request>, ws!(do_parse!( 24 | method: parse_method >> 25 | url: map_res!(take_until!(" "), str::from_utf8) >> 26 | tag!("HTTP/") >> 27 | version: map_res!(take_until!("\r"), str::from_utf8) >> 28 | (Request { method: method, url: url.into(), version: version.into() }) 29 | ))); 30 | 31 | fn run_parser(input: &str) { 32 | match parse_request(input.as_bytes()) { 33 | IResult::Done(rest, value) => println!("Rest: {:?} Value: {:?}", rest, value), 34 | IResult::Error(err) => println!("{:?}", err), 35 | IResult::Incomplete(needed) => println!("{:?}", needed) 36 | } 37 | } 38 | 39 | fn main() { 40 | let get = "GET /home/ HTTP/1.1\r\n"; 41 | run_parser(get); 42 | let post = "POST /update/ HTTP/1.1\r\n"; 43 | run_parser(post); 44 | let wrong = "WRONG /wrong/ HTTP/1.1\r\n"; 45 | run_parser(wrong); 46 | } 47 | -------------------------------------------------------------------------------- /Chapter04/chapter4/nom-ipv6/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter04/chapter4/nom-ipv6/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "compiler_error" 3 | version = "0.1.1" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | 6 | [[package]] 7 | name = "libc" 8 | version = "0.2.33" 9 | source = "registry+https://github.com/rust-lang/crates.io-index" 10 | 11 | [[package]] 12 | name = "memchr" 13 | version = "1.0.2" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | dependencies = [ 16 | "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", 17 | ] 18 | 19 | [[package]] 20 | name = "nom" 21 | version = "3.2.1" 22 | source = "registry+https://github.com/rust-lang/crates.io-index" 23 | dependencies = [ 24 | "compiler_error 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 25 | "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 26 | ] 27 | 28 | [[package]] 29 | name = "nom-http" 30 | version = "0.1.0" 31 | dependencies = [ 32 | "nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 33 | ] 34 | 35 | [metadata] 36 | "checksum compiler_error 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ef975f6d3622b15ea669c8075fefa5a9bc4bfae1b8b221ab9962daff003b3047" 37 | "checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2" 38 | "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" 39 | "checksum nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b" 40 | -------------------------------------------------------------------------------- /Chapter04/chapter4/nom-ipv6/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "nom-http" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies.nom] 7 | version = "3.2.1" 8 | features = ["verbose-errors", "nightly"] 9 | -------------------------------------------------------------------------------- /Chapter04/chapter4/nom-ipv6/src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate nom; 3 | 4 | use std::net::Ipv6Addr; 5 | 6 | use nom::IResult; 7 | 8 | #[derive(Debug, PartialEq, Eq)] 9 | pub struct IPv6Header { 10 | version: u8, 11 | traffic_class: u8, 12 | flow_label: u32, 13 | payload_length: u16, 14 | next_header: u8, 15 | hop_limit: u8, 16 | source_addr: Ipv6Addr, 17 | dest_addr: Ipv6Addr, 18 | } 19 | 20 | fn slice_to_array(input: &[u8]) -> [u8; 16] { 21 | let mut array = [0u8; 16]; 22 | for (&x, p) in input.iter().zip(array.iter_mut()) { 23 | *p = x; 24 | } 25 | array 26 | } 27 | 28 | fn to_ipv6_address(i: &[u8]) -> Ipv6Addr { 29 | let arr = slice_to_array(i); 30 | Ipv6Addr::from(arr) 31 | } 32 | 33 | named!(parse_version<&[u8], u8>, bits!(take_bits!(u8, 4))); 34 | named!(parse_traffic_class<&[u8], u8>, bits!(take_bits!(u8, 8))); 35 | named!(parse_flow_label<&[u8], u32>, bits!(take_bits!(u32, 20))); 36 | named!(parse_payload_length<&[u8], u16>, bits!(take_bits!(u16, 16))); 37 | named!(parse_next_header<&[u8], u8>, bits!(take_bits!(u8, 8))); 38 | named!(parse_hop_limit<&[u8], u8>, bits!(take_bits!(u8, 8))); 39 | named!(parse_address<&[u8], Ipv6Addr>, map!(take!(16), to_ipv6_address)); 40 | 41 | named!(ipparse<&[u8], IPv6Header>, 42 | do_parse!( 43 | ver: parse_version >> 44 | cls: parse_traffic_class >> 45 | lbl: parse_flow_label >> 46 | len: parse_payload_length >> 47 | hdr: parse_next_header >> 48 | lim: parse_hop_limit >> 49 | src: parse_address >> 50 | dst: parse_address >> 51 | (IPv6Header { 52 | version: ver, 53 | traffic_class: cls, 54 | flow_label: lbl, 55 | payload_length: len, 56 | next_header: hdr, 57 | hop_limit: lim, 58 | source_addr: src, 59 | dest_addr : dst 60 | }) 61 | )); 62 | 63 | pub fn parse_ipv6_header(i: &[u8]) -> IResult<&[u8], IPv6Header> { 64 | ipparse(i) 65 | } 66 | 67 | fn main() { 68 | const EMPTY_SLICE: &'static [u8] = &[]; 69 | let bytes = [0x60, 70 | 0x00, 71 | 0x08, 0x19, 72 | 0x80, 0x00, 0x14, 0x06, 73 | 0x40, 74 | 0x2a, 0x02, 0x0c, 0x7d, 0x2e, 0x5d, 0x5d, 0x00, 0x24, 0xec, 0x4d, 0xd1, 0xc8, 0xdf, 0xbe, 0x75, 75 | 0x2a, 0x00, 0x14, 0x50, 0x40, 0x0c, 0x0c, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd 76 | ]; 77 | 78 | let expected = IPv6Header { 79 | version: 6, 80 | traffic_class: 0, 81 | flow_label: 33176, 82 | payload_length: 20, 83 | next_header: 6, 84 | hop_limit: 64, 85 | source_addr: "2a02:c7d:2e5d:5d00:24ec:4dd1:c8df:be75".parse().unwrap(), 86 | dest_addr: "2a00:1450:400c:c0b::bd".parse().unwrap(), 87 | }; 88 | assert_eq!(ipparse(&bytes), IResult::Done(EMPTY_SLICE, expected)); 89 | } 90 | -------------------------------------------------------------------------------- /Chapter04/chapter4/pom-string/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter04/chapter4/pom-string/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "pom" 3 | version = "1.1.0" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | 6 | [[package]] 7 | name = "pom-string" 8 | version = "0.1.0" 9 | dependencies = [ 10 | "pom 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 11 | ] 12 | 13 | [metadata] 14 | "checksum pom 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60f6ce597ecdcc9a098e7fddacb1065093a3d66446fa16c675e7e71d1b5c28e6" 15 | -------------------------------------------------------------------------------- /Chapter04/chapter4/pom-string/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pom-string" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | pom = "1.1.0" 8 | -------------------------------------------------------------------------------- /Chapter04/chapter4/pom-string/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate pom; 2 | use pom::DataInput; 3 | use pom::parser::{sym, one_of, seq}; 4 | use pom::parser::*; 5 | 6 | use std::str; 7 | 8 | fn space() -> Parser<'static, u8, ()> { 9 | one_of(b" \t\r\n").repeat(0..).discard() 10 | } 11 | 12 | fn string() -> Parser<'static, u8, String> { 13 | one_of(b"abcdefghijklmnopqrstuvwxyz").repeat(0..).convert(String::from_utf8) 14 | } 15 | 16 | fn main() { 17 | let get = b"GET /home/ HTTP/1.1\r\n"; 18 | let mut input = DataInput::new(get); 19 | let parser = (seq(b"GET") | seq(b"POST")) * space() * sym(b'/') * string() * sym(b'/') * space() * seq(b"HTTP/1.1"); 20 | let output = parser.parse(&mut input); 21 | println!("{:?}", str::from_utf8(&output.unwrap())); 22 | } 23 | -------------------------------------------------------------------------------- /Chapter04/chapter4/serde-basic/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter04/chapter4/serde-basic/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "dtoa" 3 | version = "0.4.2" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | 6 | [[package]] 7 | name = "itoa" 8 | version = "0.3.4" 9 | source = "registry+https://github.com/rust-lang/crates.io-index" 10 | 11 | [[package]] 12 | name = "linked-hash-map" 13 | version = "0.3.0" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | 16 | [[package]] 17 | name = "linked-hash-map" 18 | version = "0.4.2" 19 | source = "registry+https://github.com/rust-lang/crates.io-index" 20 | 21 | [[package]] 22 | name = "num-traits" 23 | version = "0.1.40" 24 | source = "registry+https://github.com/rust-lang/crates.io-index" 25 | 26 | [[package]] 27 | name = "quote" 28 | version = "0.3.15" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | 31 | [[package]] 32 | name = "serde" 33 | version = "1.0.17" 34 | source = "registry+https://github.com/rust-lang/crates.io-index" 35 | 36 | [[package]] 37 | name = "serde-basic" 38 | version = "0.1.0" 39 | dependencies = [ 40 | "serde 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", 41 | "serde_derive 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", 42 | "serde_json 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 43 | "serde_yaml 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 44 | ] 45 | 46 | [[package]] 47 | name = "serde_derive" 48 | version = "1.0.17" 49 | source = "registry+https://github.com/rust-lang/crates.io-index" 50 | dependencies = [ 51 | "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", 52 | "serde_derive_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", 53 | "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", 54 | ] 55 | 56 | [[package]] 57 | name = "serde_derive_internals" 58 | version = "0.16.0" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | dependencies = [ 61 | "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", 62 | "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", 63 | ] 64 | 65 | [[package]] 66 | name = "serde_json" 67 | version = "1.0.5" 68 | source = "registry+https://github.com/rust-lang/crates.io-index" 69 | dependencies = [ 70 | "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 71 | "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 72 | "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 73 | "serde 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", 74 | ] 75 | 76 | [[package]] 77 | name = "serde_yaml" 78 | version = "0.7.1" 79 | source = "registry+https://github.com/rust-lang/crates.io-index" 80 | dependencies = [ 81 | "linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 82 | "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 83 | "serde 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", 84 | "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", 85 | ] 86 | 87 | [[package]] 88 | name = "syn" 89 | version = "0.11.11" 90 | source = "registry+https://github.com/rust-lang/crates.io-index" 91 | dependencies = [ 92 | "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", 93 | "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", 94 | "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 95 | ] 96 | 97 | [[package]] 98 | name = "synom" 99 | version = "0.11.3" 100 | source = "registry+https://github.com/rust-lang/crates.io-index" 101 | dependencies = [ 102 | "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 103 | ] 104 | 105 | [[package]] 106 | name = "unicode-xid" 107 | version = "0.0.4" 108 | source = "registry+https://github.com/rust-lang/crates.io-index" 109 | 110 | [[package]] 111 | name = "yaml-rust" 112 | version = "0.3.5" 113 | source = "registry+https://github.com/rust-lang/crates.io-index" 114 | dependencies = [ 115 | "linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 116 | ] 117 | 118 | [metadata] 119 | "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" 120 | "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" 121 | "checksum linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d262045c5b87c0861b3f004610afd0e2c851e2908d08b6c870cbb9d5f494ecd" 122 | "checksum linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7860ec297f7008ff7a1e3382d7f7e1dcd69efc94751a2284bafc3d013c2aa939" 123 | "checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0" 124 | "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" 125 | "checksum serde 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "d1d023215fabcf74f35f056ec7c2e3bc492b3207443150f8673309a40ba8d10a" 126 | "checksum serde_derive 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "6751796258619faf65a21714d2208f4a7614bb28690d24a819df664b01528558" 127 | "checksum serde_derive_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd381f6d01a6616cdba8530492d453b7761b456ba974e98768a18cad2cd76f58" 128 | "checksum serde_json 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ae1e67ce320daa7e494c578e34d4b00689f23bb94512fe0ca0dfaf02ea53fb67" 129 | "checksum serde_yaml 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "49d983aa39d2884a4b422bb11bb38f4f48fa05186e17469bc31e47d01e381111" 130 | "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" 131 | "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" 132 | "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" 133 | "checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" 134 | -------------------------------------------------------------------------------- /Chapter04/chapter4/serde-basic/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "serde-basic" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | serde = "1.0" 8 | serde_derive = "1.0" 9 | serde_json = "1.0" 10 | serde_yaml = "0.7.1" 11 | -------------------------------------------------------------------------------- /Chapter04/chapter4/serde-basic/src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate serde_derive; 3 | 4 | extern crate serde; 5 | extern crate serde_json; 6 | extern crate serde_yaml; 7 | 8 | #[derive(Serialize, Deserialize, Debug)] 9 | struct ServerConfig { 10 | workers: u64, 11 | ignore: bool, 12 | auth_server: Option 13 | } 14 | 15 | fn main() { 16 | let config = ServerConfig { workers: 100, ignore: false, auth_server: Some("auth.server.io".to_string()) }; 17 | { 18 | println!("To and from YAML"); 19 | let serialized = serde_yaml::to_string(&config).unwrap(); 20 | println!("{}", serialized); 21 | let deserialized: ServerConfig = serde_yaml::from_str(&serialized).unwrap(); 22 | println!("{:?}", deserialized); 23 | } 24 | println!("\n\n"); 25 | { 26 | println!("To and from JSON"); 27 | let serialized = serde_json::to_string(&config).unwrap(); 28 | println!("{}", serialized); 29 | let deserialized: ServerConfig = serde_json::from_str(&serialized).unwrap(); 30 | println!("{:?}", deserialized); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Chapter04/chapter4/serde-custom/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter04/chapter4/serde-custom/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "dtoa" 3 | version = "0.4.2" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | 6 | [[package]] 7 | name = "itoa" 8 | version = "0.3.4" 9 | source = "registry+https://github.com/rust-lang/crates.io-index" 10 | 11 | [[package]] 12 | name = "num-traits" 13 | version = "0.1.40" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | 16 | [[package]] 17 | name = "quote" 18 | version = "0.3.15" 19 | source = "registry+https://github.com/rust-lang/crates.io-index" 20 | 21 | [[package]] 22 | name = "serde" 23 | version = "1.0.20" 24 | source = "registry+https://github.com/rust-lang/crates.io-index" 25 | 26 | [[package]] 27 | name = "serde-custom" 28 | version = "0.1.0" 29 | dependencies = [ 30 | "serde 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", 31 | "serde_derive 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", 32 | "serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 33 | "serde_test 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", 34 | ] 35 | 36 | [[package]] 37 | name = "serde_derive" 38 | version = "1.0.20" 39 | source = "registry+https://github.com/rust-lang/crates.io-index" 40 | dependencies = [ 41 | "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", 42 | "serde_derive_internals 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", 43 | "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", 44 | ] 45 | 46 | [[package]] 47 | name = "serde_derive_internals" 48 | version = "0.17.0" 49 | source = "registry+https://github.com/rust-lang/crates.io-index" 50 | dependencies = [ 51 | "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", 52 | "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", 53 | ] 54 | 55 | [[package]] 56 | name = "serde_json" 57 | version = "1.0.6" 58 | source = "registry+https://github.com/rust-lang/crates.io-index" 59 | dependencies = [ 60 | "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 61 | "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 62 | "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 63 | "serde 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", 64 | ] 65 | 66 | [[package]] 67 | name = "serde_test" 68 | version = "1.0.20" 69 | source = "registry+https://github.com/rust-lang/crates.io-index" 70 | dependencies = [ 71 | "serde 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", 72 | ] 73 | 74 | [[package]] 75 | name = "syn" 76 | version = "0.11.11" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | dependencies = [ 79 | "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", 80 | "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", 81 | "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 82 | ] 83 | 84 | [[package]] 85 | name = "synom" 86 | version = "0.11.3" 87 | source = "registry+https://github.com/rust-lang/crates.io-index" 88 | dependencies = [ 89 | "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 90 | ] 91 | 92 | [[package]] 93 | name = "unicode-xid" 94 | version = "0.0.4" 95 | source = "registry+https://github.com/rust-lang/crates.io-index" 96 | 97 | [metadata] 98 | "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" 99 | "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" 100 | "checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0" 101 | "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" 102 | "checksum serde 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "5a2b181dd2b4a6353e828e44807269a761d3ecbc388a1f5ed3998ea69a516d9c" 103 | "checksum serde_derive 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "31ce3c16ec18abb97d977f75880986549213b0c18f2695eda8b31eadc96eda4a" 104 | "checksum serde_derive_internals 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32f1926285523b2db55df263d2aa4eb69ddcfa7a7eade6430323637866b513ab" 105 | "checksum serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e4586746d1974a030c48919731ecffd0ed28d0c40749d0d18d43b3a7d6c9b20e" 106 | "checksum serde_test 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "6d5d642cfaa675f56208559edec285e9b6d7e27ee9e81802462c9a0a224d5711" 107 | "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" 108 | "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" 109 | "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" 110 | -------------------------------------------------------------------------------- /Chapter04/chapter4/serde-custom/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "serde-custom" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | serde = "1.0" 8 | serde_derive = "1.0" 9 | serde_json = "1.0" 10 | serde_test = "1.0" 11 | -------------------------------------------------------------------------------- /Chapter04/chapter4/serde-custom/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate serde; 2 | extern crate serde_json; 3 | extern crate serde_test; 4 | 5 | use serde::ser::{Serialize, Serializer, SerializeStruct}; 6 | use serde::de::{self, Deserialize, Deserializer, Visitor, MapAccess}; 7 | 8 | use std::fmt; 9 | 10 | #[derive(Debug, PartialEq)] 11 | struct KubeConfig { 12 | port: u8, 13 | healthz_port: u8, 14 | max_pods: u8, 15 | } 16 | 17 | impl Serialize for KubeConfig { 18 | fn serialize(&self, serializer: S) -> Result 19 | where 20 | S: Serializer, 21 | { 22 | let mut state = serializer.serialize_struct("KubeConfig", 3)?; 23 | state.serialize_field("port", &self.port)?; 24 | state.serialize_field("healthz_port", &self.healthz_port)?; 25 | state.serialize_field("max_pods", &self.max_pods)?; 26 | state.end() 27 | } 28 | } 29 | 30 | impl<'de> Deserialize<'de> for KubeConfig { 31 | fn deserialize(deserializer: D) -> Result 32 | where 33 | D: Deserializer<'de>, 34 | { 35 | enum Field { 36 | Port, 37 | HealthzPort, 38 | MaxPods, 39 | }; 40 | 41 | impl<'de> Deserialize<'de> for Field { 42 | fn deserialize(deserializer: D) -> Result 43 | where 44 | D: Deserializer<'de>, 45 | { 46 | struct FieldVisitor; 47 | 48 | impl<'de> Visitor<'de> for FieldVisitor { 49 | type Value = Field; 50 | 51 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 52 | formatter.write_str("`port` or `healthz_port` or `max_pods`") 53 | } 54 | 55 | fn visit_str(self, value: &str) -> Result 56 | where 57 | E: de::Error, 58 | { 59 | match value { 60 | "port" => Ok(Field::Port), 61 | "healthz_port" => Ok(Field::HealthzPort), 62 | "max_pods" => Ok(Field::MaxPods), 63 | _ => Err(de::Error::unknown_field(value, FIELDS)), 64 | } 65 | } 66 | } 67 | 68 | deserializer.deserialize_identifier(FieldVisitor) 69 | } 70 | } 71 | 72 | struct KubeConfigVisitor; 73 | 74 | impl<'de> Visitor<'de> for KubeConfigVisitor { 75 | type Value = KubeConfig; 76 | 77 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 78 | formatter.write_str("struct KubeConfig") 79 | } 80 | 81 | fn visit_map(self, mut map: V) -> Result 82 | where 83 | V: MapAccess<'de>, 84 | { 85 | let mut port = None; 86 | let mut hport = None; 87 | let mut max = None; 88 | while let Some(key) = map.next_key()? { 89 | match key { 90 | Field::Port => { 91 | if port.is_some() { 92 | return Err(de::Error::duplicate_field("port")); 93 | } 94 | port = Some(map.next_value()?); 95 | } 96 | Field::HealthzPort => { 97 | if hport.is_some() { 98 | return Err(de::Error::duplicate_field("healthz_port")); 99 | } 100 | hport = Some(map.next_value()?); 101 | } 102 | Field::MaxPods => { 103 | if max.is_some() { 104 | return Err(de::Error::duplicate_field("max_pods")); 105 | } 106 | max = Some(map.next_value()?); 107 | } 108 | } 109 | } 110 | let port = port.ok_or_else(|| de::Error::missing_field("port"))?; 111 | let hport = hport.ok_or_else( 112 | || de::Error::missing_field("healthz_port"), 113 | )?; 114 | let max = max.ok_or_else(|| de::Error::missing_field("max_pods"))?; 115 | Ok(KubeConfig { 116 | port: port, 117 | healthz_port: hport, 118 | max_pods: max, 119 | }) 120 | } 121 | } 122 | 123 | const FIELDS: &'static [&'static str] = &["port", "healthz_port", "max_pods"]; 124 | deserializer.deserialize_struct("KubeConfig", FIELDS, KubeConfigVisitor) 125 | } 126 | } 127 | 128 | fn main() { 129 | let c = KubeConfig { 130 | port: 10, 131 | healthz_port: 11, 132 | max_pods: 12, 133 | }; 134 | let serialized = serde_json::to_string(&c).unwrap(); 135 | println!("{:?}", serialized); 136 | } 137 | 138 | #[test] 139 | fn test_ser_de() { 140 | use serde_test::{Token, assert_de_tokens}; 141 | let c = KubeConfig { 142 | port: 10, 143 | healthz_port: 11, 144 | max_pods: 12, 145 | }; 146 | 147 | assert_de_tokens( 148 | &c, 149 | &[ 150 | Token::Struct { 151 | name: "KubeConfig", 152 | len: 3, 153 | }, 154 | Token::Str("port"), 155 | Token::U8(10), 156 | Token::Str("healthz_port"), 157 | Token::U8(11), 158 | Token::Str("max_pods"), 159 | Token::U8(12), 160 | Token::StructEnd, 161 | ], 162 | ); 163 | } 164 | -------------------------------------------------------------------------------- /Chapter04/chapter4/serde-server/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter04/chapter4/serde-server/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "dtoa" 3 | version = "0.4.2" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | 6 | [[package]] 7 | name = "itoa" 8 | version = "0.3.4" 9 | source = "registry+https://github.com/rust-lang/crates.io-index" 10 | 11 | [[package]] 12 | name = "num-traits" 13 | version = "0.1.40" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | 16 | [[package]] 17 | name = "quote" 18 | version = "0.3.15" 19 | source = "registry+https://github.com/rust-lang/crates.io-index" 20 | 21 | [[package]] 22 | name = "serde" 23 | version = "1.0.18" 24 | source = "registry+https://github.com/rust-lang/crates.io-index" 25 | 26 | [[package]] 27 | name = "serde-server" 28 | version = "0.1.0" 29 | dependencies = [ 30 | "serde 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", 31 | "serde_derive 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", 32 | "serde_json 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 33 | ] 34 | 35 | [[package]] 36 | name = "serde_derive" 37 | version = "1.0.18" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | dependencies = [ 40 | "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", 41 | "serde_derive_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", 42 | "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", 43 | ] 44 | 45 | [[package]] 46 | name = "serde_derive_internals" 47 | version = "0.16.0" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | dependencies = [ 50 | "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", 51 | "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", 52 | ] 53 | 54 | [[package]] 55 | name = "serde_json" 56 | version = "1.0.5" 57 | source = "registry+https://github.com/rust-lang/crates.io-index" 58 | dependencies = [ 59 | "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 60 | "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 61 | "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 62 | "serde 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", 63 | ] 64 | 65 | [[package]] 66 | name = "syn" 67 | version = "0.11.11" 68 | source = "registry+https://github.com/rust-lang/crates.io-index" 69 | dependencies = [ 70 | "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", 71 | "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", 72 | "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 73 | ] 74 | 75 | [[package]] 76 | name = "synom" 77 | version = "0.11.3" 78 | source = "registry+https://github.com/rust-lang/crates.io-index" 79 | dependencies = [ 80 | "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 81 | ] 82 | 83 | [[package]] 84 | name = "unicode-xid" 85 | version = "0.0.4" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | 88 | [metadata] 89 | "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" 90 | "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" 91 | "checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0" 92 | "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" 93 | "checksum serde 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "395993cac4e3599c7c1b70a6a92d3b3f55f4443df9f0b5294e362285ad7c9ecb" 94 | "checksum serde_derive 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "7fa060f679fe2d5a9f7374dd4553dc907eba4f9acf183e4c7baf69eae02e6ca8" 95 | "checksum serde_derive_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd381f6d01a6616cdba8530492d453b7761b456ba974e98768a18cad2cd76f58" 96 | "checksum serde_json 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ae1e67ce320daa7e494c578e34d4b00689f23bb94512fe0ca0dfaf02ea53fb67" 97 | "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" 98 | "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" 99 | "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" 100 | -------------------------------------------------------------------------------- /Chapter04/chapter4/serde-server/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "serde-server" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | serde = "1.0" 8 | serde_derive = "1.0" 9 | serde_json = "1.0" 10 | -------------------------------------------------------------------------------- /Chapter04/chapter4/serde-server/src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate serde_derive; 3 | 4 | extern crate serde; 5 | extern crate serde_json; 6 | 7 | use std::net::{TcpListener, TcpStream}; 8 | use std::io::{stdin, BufRead, BufReader, Error, Write}; 9 | use std::{env, str, thread}; 10 | 11 | #[derive(Serialize, Deserialize, Debug)] 12 | struct Point3D { 13 | x: u32, 14 | y: u32, 15 | z: u32, 16 | } 17 | 18 | fn handle_client(stream: TcpStream) -> Result<(), Error> { 19 | println!("Incoming connection from: {}", stream.peer_addr()?); 20 | let mut data = Vec::new(); 21 | let mut stream = BufReader::new(stream); 22 | 23 | loop { 24 | data.clear(); 25 | 26 | let bytes_read = stream.read_until(b'\n', &mut data)?; 27 | if bytes_read == 0 { 28 | return Ok(()); 29 | } 30 | let input: Point3D = serde_json::from_slice(&data)?; 31 | let value = input.x.pow(2) + input.y.pow(2) + input.z.pow(2); 32 | 33 | write!(stream.get_mut(), "{}", f64::from(value).sqrt())?; 34 | write!(stream.get_mut(), "{}", "\n")?; 35 | } 36 | } 37 | 38 | fn main() { 39 | let args: Vec<_> = env::args().collect(); 40 | if args.len() != 2 { 41 | eprintln!("Please provide --client or --server as argument"); 42 | std::process::exit(1); 43 | } 44 | if args[1] == "--server" { 45 | let listener = TcpListener::bind("0.0.0.0:8888").expect("Could not bind"); 46 | for stream in listener.incoming() { 47 | match stream { 48 | Err(e) => eprintln!("failed: {}", e), 49 | Ok(stream) => { 50 | thread::spawn(move || { 51 | handle_client(stream).unwrap_or_else(|error| eprintln!("{:?}", error)); 52 | }); 53 | } 54 | } 55 | } 56 | } else if args[1] == "--client" { 57 | let mut stream = TcpStream::connect("127.0.0.1:8888").expect("Could not connect to server"); 58 | println!("Please provide a 3D point as three comma separated integers"); 59 | loop { 60 | let mut input = String::new(); 61 | let mut buffer: Vec = Vec::new(); 62 | stdin() 63 | .read_line(&mut input) 64 | .expect("Failed to read from stdin"); 65 | let parts: Vec<&str> = input.trim_matches('\n').split(',').collect(); 66 | let point = Point3D { 67 | x: parts[0].parse().unwrap(), 68 | y: parts[1].parse().unwrap(), 69 | z: parts[2].parse().unwrap(), 70 | }; 71 | stream 72 | .write_all(serde_json::to_string(&point).unwrap().as_bytes()) 73 | .expect("Failed to write to server"); 74 | stream.write_all(b"\n").expect("Failed to write to server"); 75 | 76 | let mut reader = BufReader::new(&stream); 77 | reader 78 | .read_until(b'\n', &mut buffer) 79 | .expect("Could not read into buffer"); 80 | let input = str::from_utf8(&buffer).expect("Could not write buffer as string"); 81 | if input == "" { 82 | eprintln!("Empty response from server"); 83 | } 84 | print!("Response from server {}", input); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /Chapter05/ftp-example/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter05/ftp-example/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "aho-corasick" 3 | version = "0.5.3" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | dependencies = [ 6 | "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", 7 | ] 8 | 9 | [[package]] 10 | name = "chrono" 11 | version = "0.2.25" 12 | source = "registry+https://github.com/rust-lang/crates.io-index" 13 | dependencies = [ 14 | "num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 15 | "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", 16 | ] 17 | 18 | [[package]] 19 | name = "ftp" 20 | version = "2.2.1" 21 | source = "registry+https://github.com/rust-lang/crates.io-index" 22 | dependencies = [ 23 | "chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)", 24 | "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", 25 | "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", 26 | ] 27 | 28 | [[package]] 29 | name = "ftp-example" 30 | version = "0.1.0" 31 | dependencies = [ 32 | "ftp 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 33 | ] 34 | 35 | [[package]] 36 | name = "kernel32-sys" 37 | version = "0.2.2" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | dependencies = [ 40 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 41 | "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 42 | ] 43 | 44 | [[package]] 45 | name = "lazy_static" 46 | version = "0.1.16" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | 49 | [[package]] 50 | name = "libc" 51 | version = "0.2.33" 52 | source = "registry+https://github.com/rust-lang/crates.io-index" 53 | 54 | [[package]] 55 | name = "memchr" 56 | version = "0.1.11" 57 | source = "registry+https://github.com/rust-lang/crates.io-index" 58 | dependencies = [ 59 | "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", 60 | ] 61 | 62 | [[package]] 63 | name = "num" 64 | version = "0.1.40" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | dependencies = [ 67 | "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", 68 | "num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", 69 | "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 70 | ] 71 | 72 | [[package]] 73 | name = "num-integer" 74 | version = "0.1.35" 75 | source = "registry+https://github.com/rust-lang/crates.io-index" 76 | dependencies = [ 77 | "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 78 | ] 79 | 80 | [[package]] 81 | name = "num-iter" 82 | version = "0.1.34" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | dependencies = [ 85 | "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", 86 | "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 87 | ] 88 | 89 | [[package]] 90 | name = "num-traits" 91 | version = "0.1.40" 92 | source = "registry+https://github.com/rust-lang/crates.io-index" 93 | 94 | [[package]] 95 | name = "redox_syscall" 96 | version = "0.1.31" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | 99 | [[package]] 100 | name = "regex" 101 | version = "0.1.80" 102 | source = "registry+https://github.com/rust-lang/crates.io-index" 103 | dependencies = [ 104 | "aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", 105 | "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", 106 | "regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 107 | "thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", 108 | "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 109 | ] 110 | 111 | [[package]] 112 | name = "regex-syntax" 113 | version = "0.3.9" 114 | source = "registry+https://github.com/rust-lang/crates.io-index" 115 | 116 | [[package]] 117 | name = "thread-id" 118 | version = "2.0.0" 119 | source = "registry+https://github.com/rust-lang/crates.io-index" 120 | dependencies = [ 121 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 122 | "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", 123 | ] 124 | 125 | [[package]] 126 | name = "thread_local" 127 | version = "0.2.7" 128 | source = "registry+https://github.com/rust-lang/crates.io-index" 129 | dependencies = [ 130 | "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 131 | ] 132 | 133 | [[package]] 134 | name = "time" 135 | version = "0.1.38" 136 | source = "registry+https://github.com/rust-lang/crates.io-index" 137 | dependencies = [ 138 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 139 | "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", 140 | "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", 141 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 142 | ] 143 | 144 | [[package]] 145 | name = "utf8-ranges" 146 | version = "0.1.3" 147 | source = "registry+https://github.com/rust-lang/crates.io-index" 148 | 149 | [[package]] 150 | name = "winapi" 151 | version = "0.2.8" 152 | source = "registry+https://github.com/rust-lang/crates.io-index" 153 | 154 | [[package]] 155 | name = "winapi-build" 156 | version = "0.1.1" 157 | source = "registry+https://github.com/rust-lang/crates.io-index" 158 | 159 | [metadata] 160 | "checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" 161 | "checksum chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9213f7cd7c27e95c2b57c49f0e69b1ea65b27138da84a170133fd21b07659c00" 162 | "checksum ftp 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f4679a8d2e434666811ee01ecd9814c28827a20166db65bbb8137c658ff37fd1" 163 | "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" 164 | "checksum lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "cf186d1a8aa5f5bee5fd662bc9c1b949e0259e1bcc379d1f006847b0080c7417" 165 | "checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2" 166 | "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" 167 | "checksum num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "a311b77ebdc5dd4cf6449d81e4135d9f0e3b153839ac90e648a8ef538f923525" 168 | "checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba" 169 | "checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01" 170 | "checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0" 171 | "checksum redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "8dde11f18c108289bef24469638a04dce49da56084f2d50618b226e47eb04509" 172 | "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" 173 | "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" 174 | "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" 175 | "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" 176 | "checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520" 177 | "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" 178 | "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" 179 | "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" 180 | -------------------------------------------------------------------------------- /Chapter05/ftp-example/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ftp-example" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies.ftp] 7 | version = "2.2.1" 8 | -------------------------------------------------------------------------------- /Chapter05/ftp-example/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate ftp; 2 | 3 | use std::str; 4 | use std::io::Cursor; 5 | use ftp::{FtpStream, FtpError}; 6 | 7 | fn run_ftp(addr: &str, user: &str, pass: &str) -> Result<(), FtpError> { 8 | let mut ftp_stream = FtpStream::connect((addr, 21))?; 9 | ftp_stream.login(user, pass)?; 10 | println!("current dir: {}", ftp_stream.pwd()?); 11 | 12 | ftp_stream.simple_retr("5MB.zip")?; 13 | println!("Downloaded file"); 14 | 15 | let data = "A random string to write to a file"; 16 | let mut reader = Cursor::new(data); 17 | ftp_stream.cwd("/upload")?; 18 | ftp_stream.put("my_file.txt", &mut reader)?; 19 | 20 | ftp_stream.quit() 21 | } 22 | 23 | fn main() { 24 | run_ftp("speedtest.tele2.net", "anonymous", "anonymous").unwrap(); 25 | } 26 | -------------------------------------------------------------------------------- /Chapter05/grpc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "grpc_example" 3 | version = "0.1.0" 4 | authors = ["Foo"] 5 | 6 | [dependencies] 7 | protobuf = "1.4.1" 8 | grpc = "0.2.1" 9 | tls-api = "0.1.8" 10 | 11 | [build-dependencies] 12 | protoc-rust-grpc = "0.2.1" 13 | -------------------------------------------------------------------------------- /Chapter05/grpc/build.rs: -------------------------------------------------------------------------------- 1 | extern crate protoc_rust_grpc; 2 | 3 | fn main() { 4 | protoc_rust_grpc::run(protoc_rust_grpc::Args { 5 | out_dir: "src", 6 | includes: &[], 7 | input: &["foobar.proto"], 8 | rust_protobuf: true, 9 | }).expect("protoc-rust-grpc"); 10 | } 11 | -------------------------------------------------------------------------------- /Chapter05/grpc/foobar.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package foobar; 4 | 5 | service FooBarService { 6 | rpc record_cab_location(CabLocationRequest) returns (CabLocationResponse); 7 | rpc get_cabs(GetCabRequest) returns (GetCabResponse); 8 | } 9 | 10 | message CabLocationRequest { 11 | string name = 1; 12 | Location location = 2; 13 | } 14 | 15 | message CabLocationResponse { 16 | bool accepted = 1; 17 | } 18 | 19 | message GetCabRequest { 20 | Location location = 1; 21 | } 22 | 23 | message GetCabResponse { 24 | repeated Cab cabs = 1; 25 | } 26 | 27 | message Cab { 28 | string name = 1; 29 | Location location = 2; 30 | } 31 | 32 | message Location { 33 | float latitude = 1; 34 | float longitude = 2; 35 | } 36 | -------------------------------------------------------------------------------- /Chapter05/grpc/src/bin/client.rs: -------------------------------------------------------------------------------- 1 | extern crate grpc_example; 2 | extern crate grpc; 3 | 4 | use grpc_example::foobar::*; 5 | use grpc_example::foobar_grpc::*; 6 | 7 | 8 | fn main() { 9 | let client = FooBarServiceClient::new_plain("127.0.0.1", 9001, Default::default()).unwrap(); 10 | 11 | let mut req = CabLocationRequest::new(); 12 | req.set_name("foo".to_string()); 13 | 14 | let mut location = Location::new(); 15 | location.latitude = 40.730610; 16 | location.longitude = -73.935242; 17 | req.set_location(location); 18 | 19 | let resp = client.record_cab_location(grpc::RequestOptions::new(), req); 20 | match resp.wait() { 21 | Err(e) => panic!("{:?}", e), 22 | Ok((_, r, _)) => println!("{:?}", r), 23 | } 24 | 25 | let mut nearby_req = GetCabRequest::new(); 26 | let mut location = Location::new(); 27 | location.latitude = 40.730610; 28 | location.longitude = -73.935242; 29 | nearby_req.set_location(location); 30 | 31 | let nearby_resp = client.get_cabs(grpc::RequestOptions::new(), nearby_req); 32 | match nearby_resp.wait() { 33 | Err(e) => panic!("{:?}", e), 34 | Ok((_, cabs, _)) => println!("{:?}", cabs), 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Chapter05/grpc/src/bin/server.rs: -------------------------------------------------------------------------------- 1 | extern crate grpc_example; 2 | extern crate grpc; 3 | extern crate protobuf; 4 | 5 | use std::thread; 6 | 7 | use grpc_example::foobar_grpc::*; 8 | use grpc_example::foobar::*; 9 | 10 | struct FooBarServer; 11 | 12 | impl FooBarService for FooBarServer { 13 | fn record_cab_location(&self, 14 | _m: grpc::RequestOptions, 15 | req: CabLocationRequest) 16 | -> grpc::SingleResponse { 17 | let mut r = CabLocationResponse::new(); 18 | 19 | println!("Recorded cab {} at {}, {}", req.get_name(), req.get_location().latitude, req.get_location().longitude); 20 | 21 | r.set_accepted(true); 22 | grpc::SingleResponse::completed(r) 23 | } 24 | 25 | fn get_cabs(&self, 26 | _m: grpc::RequestOptions, 27 | _req: GetCabRequest) 28 | -> grpc::SingleResponse { 29 | let mut r = GetCabResponse::new(); 30 | 31 | let mut location = Location::new(); 32 | location.latitude = 40.7128; 33 | location.longitude = -74.0060; 34 | 35 | let mut one = Cab::new(); 36 | one.set_name("Limo".to_owned()); 37 | one.set_location(location.clone()); 38 | 39 | let mut two = Cab::new(); 40 | two.set_name("Merc".to_owned()); 41 | two.set_location(location.clone()); 42 | 43 | let vec = vec![one, two]; 44 | let cabs = ::protobuf::RepeatedField::from_vec(vec); 45 | 46 | r.set_cabs(cabs); 47 | 48 | grpc::SingleResponse::completed(r) 49 | } 50 | } 51 | 52 | fn main() { 53 | let mut server = grpc::ServerBuilder::new_plain(); 54 | server.http.set_port(9001); 55 | server.add_service(FooBarServiceServer::new_service_def(FooBarServer)); 56 | server.http.set_cpu_pool_threads(4); 57 | let _server = server.build().expect("Could not start server"); 58 | loop { 59 | thread::park(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Chapter05/grpc/src/foobar_grpc.rs: -------------------------------------------------------------------------------- 1 | // This file is generated. Do not edit 2 | // @generated 3 | 4 | // https://github.com/Manishearth/rust-clippy/issues/702 5 | #![allow(unknown_lints)] 6 | #![allow(clippy)] 7 | 8 | #![cfg_attr(rustfmt, rustfmt_skip)] 9 | 10 | #![allow(box_pointers)] 11 | #![allow(dead_code)] 12 | #![allow(missing_docs)] 13 | #![allow(non_camel_case_types)] 14 | #![allow(non_snake_case)] 15 | #![allow(non_upper_case_globals)] 16 | #![allow(trivial_casts)] 17 | #![allow(unsafe_code)] 18 | #![allow(unused_imports)] 19 | #![allow(unused_results)] 20 | 21 | 22 | // interface 23 | 24 | pub trait FooBarService { 25 | fn record_cab_location(&self, o: ::grpc::RequestOptions, p: super::foobar::CabLocationRequest) -> ::grpc::SingleResponse; 26 | 27 | fn get_cabs(&self, o: ::grpc::RequestOptions, p: super::foobar::GetCabRequest) -> ::grpc::SingleResponse; 28 | } 29 | 30 | // client 31 | 32 | pub struct FooBarServiceClient { 33 | grpc_client: ::grpc::Client, 34 | method_record_cab_location: ::std::sync::Arc<::grpc::rt::MethodDescriptor>, 35 | method_get_cabs: ::std::sync::Arc<::grpc::rt::MethodDescriptor>, 36 | } 37 | 38 | impl FooBarServiceClient { 39 | pub fn with_client(grpc_client: ::grpc::Client) -> Self { 40 | FooBarServiceClient { 41 | grpc_client: grpc_client, 42 | method_record_cab_location: ::std::sync::Arc::new(::grpc::rt::MethodDescriptor { 43 | name: "/foobar.FooBarService/record_cab_location".to_string(), 44 | streaming: ::grpc::rt::GrpcStreaming::Unary, 45 | req_marshaller: Box::new(::grpc::protobuf::MarshallerProtobuf), 46 | resp_marshaller: Box::new(::grpc::protobuf::MarshallerProtobuf), 47 | }), 48 | method_get_cabs: ::std::sync::Arc::new(::grpc::rt::MethodDescriptor { 49 | name: "/foobar.FooBarService/get_cabs".to_string(), 50 | streaming: ::grpc::rt::GrpcStreaming::Unary, 51 | req_marshaller: Box::new(::grpc::protobuf::MarshallerProtobuf), 52 | resp_marshaller: Box::new(::grpc::protobuf::MarshallerProtobuf), 53 | }), 54 | } 55 | } 56 | 57 | pub fn new_plain(host: &str, port: u16, conf: ::grpc::ClientConf) -> ::grpc::Result { 58 | ::grpc::Client::new_plain(host, port, conf).map(|c| { 59 | FooBarServiceClient::with_client(c) 60 | }) 61 | } 62 | pub fn new_tls(host: &str, port: u16, conf: ::grpc::ClientConf) -> ::grpc::Result { 63 | ::grpc::Client::new_tls::(host, port, conf).map(|c| { 64 | FooBarServiceClient::with_client(c) 65 | }) 66 | } 67 | } 68 | 69 | impl FooBarService for FooBarServiceClient { 70 | fn record_cab_location(&self, o: ::grpc::RequestOptions, p: super::foobar::CabLocationRequest) -> ::grpc::SingleResponse { 71 | self.grpc_client.call_unary(o, p, self.method_record_cab_location.clone()) 72 | } 73 | 74 | fn get_cabs(&self, o: ::grpc::RequestOptions, p: super::foobar::GetCabRequest) -> ::grpc::SingleResponse { 75 | self.grpc_client.call_unary(o, p, self.method_get_cabs.clone()) 76 | } 77 | } 78 | 79 | // server 80 | 81 | pub struct FooBarServiceServer; 82 | 83 | 84 | impl FooBarServiceServer { 85 | pub fn new_service_def(handler: H) -> ::grpc::rt::ServerServiceDefinition { 86 | let handler_arc = ::std::sync::Arc::new(handler); 87 | ::grpc::rt::ServerServiceDefinition::new("/foobar.FooBarService", 88 | vec![ 89 | ::grpc::rt::ServerMethod::new( 90 | ::std::sync::Arc::new(::grpc::rt::MethodDescriptor { 91 | name: "/foobar.FooBarService/record_cab_location".to_string(), 92 | streaming: ::grpc::rt::GrpcStreaming::Unary, 93 | req_marshaller: Box::new(::grpc::protobuf::MarshallerProtobuf), 94 | resp_marshaller: Box::new(::grpc::protobuf::MarshallerProtobuf), 95 | }), 96 | { 97 | let handler_copy = handler_arc.clone(); 98 | ::grpc::rt::MethodHandlerUnary::new(move |o, p| handler_copy.record_cab_location(o, p)) 99 | }, 100 | ), 101 | ::grpc::rt::ServerMethod::new( 102 | ::std::sync::Arc::new(::grpc::rt::MethodDescriptor { 103 | name: "/foobar.FooBarService/get_cabs".to_string(), 104 | streaming: ::grpc::rt::GrpcStreaming::Unary, 105 | req_marshaller: Box::new(::grpc::protobuf::MarshallerProtobuf), 106 | resp_marshaller: Box::new(::grpc::protobuf::MarshallerProtobuf), 107 | }), 108 | { 109 | let handler_copy = handler_arc.clone(); 110 | ::grpc::rt::MethodHandlerUnary::new(move |o, p| handler_copy.get_cabs(o, p)) 111 | }, 112 | ), 113 | ], 114 | ) 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /Chapter05/grpc/src/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate protobuf; 2 | extern crate grpc; 3 | extern crate tls_api; 4 | 5 | pub mod foobar; 6 | pub mod foobar_grpc; 7 | -------------------------------------------------------------------------------- /Chapter05/lettre-example/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter05/lettre-example/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "lettre-example" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | lettre = "0.7" 8 | uuid = "0.5.1" 9 | native-tls = "0.1.4" 10 | -------------------------------------------------------------------------------- /Chapter05/lettre-example/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate uuid; 2 | extern crate lettre; 3 | extern crate native_tls; 4 | 5 | use std::env; 6 | use lettre::{SendableEmail, EmailAddress, EmailTransport}; 7 | use lettre::smtp::{SmtpTransportBuilder, SUBMISSION_PORT}; 8 | use lettre::smtp::authentication::Credentials; 9 | use lettre::smtp::client::net::ClientTlsParameters; 10 | 11 | use native_tls::TlsConnector; 12 | 13 | struct CrashReport { 14 | to: Vec, 15 | from: EmailAddress, 16 | message_id: String, 17 | message: Vec, 18 | } 19 | 20 | impl CrashReport { 21 | pub fn new(from_address: EmailAddress, 22 | to_addresses: Vec, 23 | message_id: String, 24 | message: String) -> CrashReport { 25 | CrashReport { from: from_address, 26 | to: to_addresses, 27 | message_id: message_id, 28 | message: message.into_bytes() 29 | } 30 | } 31 | } 32 | 33 | impl<'a> SendableEmail<'a, &'a [u8]> for CrashReport { 34 | fn to(&self) -> Vec { 35 | self.to.clone() 36 | } 37 | 38 | fn from(&self) -> EmailAddress { 39 | self.from.clone() 40 | } 41 | 42 | fn message_id(&self) -> String { 43 | self.message_id.clone() 44 | } 45 | 46 | fn message(&'a self) -> Box<&[u8]> { 47 | Box::new(self.message.as_slice()) 48 | } 49 | } 50 | 51 | fn main() { 52 | let server = "smtp.foo.bar"; 53 | let connector = TlsConnector::builder().unwrap().build().unwrap(); 54 | let mut transport = SmtpTransportBuilder::new((server, SUBMISSION_PORT), lettre::ClientSecurity::Opportunistic(::new(server.to_string(), connector))) 55 | .expect("Failed to create transport") 56 | .credentials(Credentials::new(env::var("USERNAME").unwrap_or_else(|_| "user".to_string()), 57 | env::var("PASSWORD").unwrap_or_else(|_| "password".to_string()))) 58 | .build(); 59 | let report = CrashReport::new(EmailAddress::new("foo@bar.com".to_string()), vec![EmailAddress::new("foo@bar.com".to_string())], "foo".to_string(), "OOPS!".to_string()); 60 | transport.send(&report).expect("Failed to send the report"); 61 | } 62 | -------------------------------------------------------------------------------- /Chapter05/tftp-example/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter05/tftp-example/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tftp-example" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | tftp_server = "0.0.2" 8 | -------------------------------------------------------------------------------- /Chapter05/tftp-example/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate tftp_server; 2 | 3 | use tftp_server::server::TftpServer; 4 | 5 | use std::net::SocketAddr; 6 | use std::str::FromStr; 7 | 8 | fn main() { 9 | let addr = format!("0.0.0.0:{}", 69); 10 | let socket_addr = SocketAddr::from_str(addr.as_str()).expect("Error parsing address"); 11 | let mut server = TftpServer::new_from_addr(&socket_addr).expect("Error creating server"); 12 | match server.run() { 13 | Ok(_) => println!("Server completed successfully!"), 14 | Err(e) => println!("Error: {:?}", e), 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter06/ch6/hyper-server-faster/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter06/ch6/hyper-server-faster/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hyper-server-faster" 3 | version = "0.1.0" 4 | authors = ["Foo"] 5 | 6 | [dependencies] 7 | hyper = "0.11.7" 8 | futures = "0.1.17" 9 | net2 = "0.2.31" 10 | tokio-core = "0.1.10" 11 | num_cpus = "1.0" 12 | -------------------------------------------------------------------------------- /Chapter06/ch6/hyper-server-faster/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate futures; 2 | extern crate hyper; 3 | extern crate net2; 4 | extern crate tokio_core; 5 | extern crate num_cpus; 6 | 7 | use futures::Stream; 8 | use net2::unix::UnixTcpBuilderExt; 9 | use tokio_core::reactor::Core; 10 | use tokio_core::net::TcpListener; 11 | use std::{thread, time}; 12 | use std::net::SocketAddr; 13 | use std::sync::Arc; 14 | use futures::future::FutureResult; 15 | use hyper::{Get, StatusCode}; 16 | use hyper::header::ContentLength; 17 | use hyper::server::{Http, Service, Request, Response}; 18 | 19 | fn heavy_work() -> String { 20 | let duration = time::Duration::from_millis(100); 21 | thread::sleep(duration); 22 | "done".to_string() 23 | } 24 | 25 | #[derive(Clone, Copy)] 26 | struct Echo; 27 | 28 | impl Service for Echo { 29 | type Request = Request; 30 | type Response = Response; 31 | type Error = hyper::Error; 32 | type Future = FutureResult; 33 | 34 | fn call(&self, req: Request) -> Self::Future { 35 | futures::future::ok(match (req.method(), req.path()) { 36 | (&Get, "/data") => { 37 | let b = heavy_work().into_bytes(); 38 | Response::new() 39 | .with_header(ContentLength(b.len() as u64)) 40 | .with_body(b) 41 | } 42 | _ => Response::new().with_status(StatusCode::NotFound), 43 | }) 44 | } 45 | } 46 | 47 | fn serve(addr: &SocketAddr, protocol: &Http) { 48 | let mut core = Core::new().unwrap(); 49 | let handle = core.handle(); 50 | let listener = net2::TcpBuilder::new_v4() 51 | .unwrap() 52 | .reuse_port(true) 53 | .unwrap() 54 | .bind(addr) 55 | .unwrap() 56 | .listen(128) 57 | .unwrap(); 58 | let listener = TcpListener::from_listener(listener, addr, &handle).unwrap(); 59 | core.run(listener.incoming().for_each(|(socket, addr)| { 60 | protocol.bind_connection(&handle, socket, addr, Echo); 61 | Ok(()) 62 | })).unwrap(); 63 | } 64 | 65 | fn start_server(num: usize, addr: &str) { 66 | let addr = addr.parse().unwrap(); 67 | 68 | let protocol = Arc::new(Http::new()); 69 | { 70 | for _ in 0..num - 1 { 71 | let protocol = Arc::clone(&protocol); 72 | thread::spawn(move || serve(&addr, &protocol)); 73 | } 74 | } 75 | serve(&addr, &protocol); 76 | } 77 | 78 | 79 | fn main() { 80 | start_server(num_cpus::get(), "0.0.0.0:3000"); 81 | } 82 | -------------------------------------------------------------------------------- /Chapter06/ch6/hyper-server/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter06/ch6/hyper-server/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hyper-server" 3 | version = "0.1.0" 4 | authors = ["Foo"] 5 | 6 | [dependencies] 7 | hyper = "0.11.7" 8 | futures = "0.1.17" 9 | -------------------------------------------------------------------------------- /Chapter06/ch6/hyper-server/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate hyper; 2 | extern crate futures; 3 | 4 | use std::{ thread, time }; 5 | use futures::future::FutureResult; 6 | use hyper::{Get, StatusCode}; 7 | use hyper::header::ContentLength; 8 | use hyper::server::{Http, Service, Request, Response}; 9 | 10 | fn heavy_work() -> String { 11 | let duration = time::Duration::from_millis(100); 12 | thread::sleep(duration); 13 | "done".to_string() 14 | } 15 | 16 | #[derive(Clone, Copy)] 17 | struct Echo; 18 | 19 | impl Service for Echo { 20 | type Request = Request; 21 | type Response = Response; 22 | type Error = hyper::Error; 23 | type Future = FutureResult; 24 | 25 | fn call(&self, req: Request) -> Self::Future { 26 | futures::future::ok(match (req.method(), req.path()) { 27 | (&Get, "/data") => { 28 | let b = heavy_work().into_bytes(); 29 | Response::new() 30 | .with_header(ContentLength(b.len() as u64)) 31 | .with_body(b) 32 | } 33 | _ => Response::new().with_status(StatusCode::NotFound), 34 | }) 35 | } 36 | } 37 | 38 | fn main() { 39 | let addr = "0.0.0.0:3000".parse().unwrap(); 40 | let server = Http::new().bind(&addr, || Ok(Echo)).unwrap(); 41 | server.run().unwrap(); 42 | } 43 | -------------------------------------------------------------------------------- /Chapter06/ch6/reqwest-async/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter06/ch6/reqwest-async/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "reqwest-async" 3 | version = "0.1.0" 4 | authors = ["Foo "] 5 | 6 | [dependencies] 7 | serde_json = "1.0.6" 8 | serde = "1.0.21" 9 | serde_derive = "1.0.21" 10 | futures = "0.1.17" 11 | tokio-core = "0.1.10" 12 | 13 | [dependencies.reqwest] 14 | version = "0.8.1" 15 | features = ["unstable"] 16 | -------------------------------------------------------------------------------- /Chapter06/ch6/reqwest-async/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate serde_json; 2 | #[macro_use] 3 | extern crate serde_derive; 4 | extern crate reqwest; 5 | extern crate futures; 6 | extern crate tokio_core; 7 | 8 | use futures::Future; 9 | use tokio_core::reactor::Core; 10 | use reqwest::unstable::async::{Client, Decoder}; 11 | use std::mem; 12 | use std::io::{self, Cursor}; 13 | use futures::Stream; 14 | 15 | #[derive(Debug, Serialize, Deserialize)] 16 | struct Post { 17 | title: String, 18 | body: String, 19 | pinned: bool, 20 | } 21 | 22 | fn main() { 23 | let mut core = Core::new().expect("Could not create core"); 24 | let url = "http://localhost:8000/posts"; 25 | let post: Post = Post { 26 | title: "Testing this".to_string(), 27 | body: "Try to write something".to_string(), 28 | pinned: true, 29 | }; 30 | let client = Client::new(&core.handle()); 31 | let res = client.post(url).json(&post).send().and_then(|mut res| { 32 | println!("{}", res.status()); 33 | Ok(()) 34 | }); 35 | core.run(res).unwrap(); 36 | 37 | let mut posts = client 38 | .get(url) 39 | .send() 40 | .and_then(|mut res| { 41 | println!("{}", res.status()); 42 | let body = mem::replace(res.body_mut(), Decoder::empty()); 43 | body.concat2().map_err(Into::into) 44 | }) 45 | .and_then(|body| { 46 | let mut body = Cursor::new(body); 47 | let mut writer: Vec = vec![]; 48 | io::copy(&mut body, &mut writer).unwrap(); 49 | let posts: Vec = serde_json::from_str(std::str::from_utf8(&writer).unwrap()) 50 | .unwrap(); 51 | for post in posts { 52 | println!("{:?}", post); 53 | } 54 | Ok(()) 55 | }); 56 | core.run(posts).unwrap(); 57 | } 58 | -------------------------------------------------------------------------------- /Chapter06/ch6/reqwest-example/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter06/ch6/reqwest-example/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "reqwest-example" 3 | version = "0.1.0" 4 | authors = ["Foo"] 5 | 6 | [dependencies] 7 | reqwest = "0.8.1" 8 | serde_json = "1.0.6" 9 | serde = "1.0.21" 10 | serde_derive = "1.0.21" 11 | -------------------------------------------------------------------------------- /Chapter06/ch6/reqwest-example/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate serde_json; 2 | #[macro_use] 3 | extern crate serde_derive; 4 | extern crate reqwest; 5 | 6 | #[derive(Debug,Serialize, Deserialize)] 7 | struct Post { 8 | title: String, 9 | body: String, 10 | pinned: bool, 11 | } 12 | 13 | fn main() { 14 | let url = "http://localhost:8000/posts"; 15 | let post: Post = Post {title: "Testing this".to_string(), body: "Try to write something".to_string(), pinned: true}; 16 | let client = reqwest::Client::new(); 17 | let res = client.post(url) 18 | .json(&post) 19 | .send() 20 | .unwrap(); 21 | println!("Got back: {}", res.status()); 22 | 23 | let mut posts = client.get(url).send().unwrap(); 24 | let json: Vec = posts.json().unwrap(); 25 | for post in json { 26 | println!("{:?}", post); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Chapter06/ch6/rocket-blog/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock 7 | #Cargo.lock 8 | #target 9 | db.sql 10 | -------------------------------------------------------------------------------- /Chapter06/ch6/rocket-blog/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Network-Programming-with-Rust/74f3650024ce3dd772300699beaa0059e2f30795/Chapter06/ch6/rocket-blog/.gitkeep -------------------------------------------------------------------------------- /Chapter06/ch6/rocket-blog/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Foo "] 3 | name = "rocket-blog" 4 | version = "0.1.0" 5 | 6 | [dependencies] 7 | rocket = "0.4.5" 8 | rocket_codegen = "0.4.5" 9 | rocket_contrib = "0.4.5" 10 | diesel = { version = "1.4.5", features = ["sqlite", "r2d2"] } 11 | dotenv = "0.10.1" 12 | serde = "1.0.115" 13 | serde_json = "1.0.57" 14 | serde_derive = "1.0.115" 15 | lazy_static = "1.4.0" 16 | r2d2 = "0.8.9" 17 | r2d2-diesel = "1.0.0" 18 | -------------------------------------------------------------------------------- /Chapter06/ch6/rocket-blog/README.md: -------------------------------------------------------------------------------- 1 | * Setup DB 2 | `DATABASE_URL=db.sql diesel migration run` 3 | * Run server 4 | `DATABASE_URL=db.sql cargo run` 5 | -------------------------------------------------------------------------------- /Chapter06/ch6/rocket-blog/migrations/2017-11-26-143245_posts/down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE posts 2 | -------------------------------------------------------------------------------- /Chapter06/ch6/rocket-blog/migrations/2017-11-26-143245_posts/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE posts ( 2 | id INTEGER PRIMARY KEY NOT NULL, 3 | title VARCHAR NOT NULL, 4 | body TEXT NOT NULL, 5 | pinned BOOLEAN NOT NULL DEFAULT 'f' 6 | ) 7 | -------------------------------------------------------------------------------- /Chapter06/ch6/rocket-blog/src/db.rs: -------------------------------------------------------------------------------- 1 | use std::ops::Deref; 2 | use dotenv::dotenv; 3 | use std::env; 4 | use diesel::sqlite::SqliteConnection; 5 | use diesel::r2d2::ConnectionManager; 6 | use r2d2; 7 | use rocket::request::{Outcome, FromRequest}; 8 | use rocket::Outcome::{Success, Failure}; 9 | use rocket::Request; 10 | use rocket::http::Status; 11 | 12 | lazy_static! { 13 | pub static ref DB_POOL: r2d2::Pool> = { 14 | dotenv().ok(); 15 | 16 | let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); 17 | let manager = ConnectionManager::::new(database_url); 18 | r2d2::Pool::builder().max_size(32).build(manager).expect("failed to create pool") 19 | }; 20 | } 21 | 22 | pub struct DB(r2d2::PooledConnection>); 23 | 24 | impl Deref for DB { 25 | type Target = SqliteConnection; 26 | 27 | fn deref(&self) -> &Self::Target { 28 | &self.0 29 | } 30 | } 31 | 32 | impl<'a, 'r> FromRequest<'a, 'r> for DB { 33 | type Error = r2d2::Error; 34 | fn from_request(_: &'a Request<'r>) -> Outcome { 35 | match DB_POOL.get() { 36 | Ok(conn) => Success(DB(conn)), 37 | Err(e) => Failure((Status::InternalServerError, e)), 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Chapter06/ch6/rocket-blog/src/error.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | use std::convert::From; 3 | use std::fmt; 4 | use diesel::result::Error as DieselError; 5 | use rocket::http::Status; 6 | use rocket::response::{Response, Responder}; 7 | use rocket::Request; 8 | 9 | #[derive(Debug)] 10 | pub enum ApiError { 11 | NotFound, 12 | InternalServerError, 13 | } 14 | 15 | impl fmt::Display for ApiError { 16 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 17 | match *self { 18 | ApiError::NotFound => f.write_str("NotFound"), 19 | ApiError::InternalServerError => f.write_str("InternalServerError"), 20 | } 21 | } 22 | } 23 | 24 | impl From for ApiError { 25 | fn from(e: DieselError) -> Self { 26 | match e { 27 | DieselError::NotFound => ApiError::NotFound, 28 | _ => ApiError::InternalServerError, 29 | } 30 | } 31 | } 32 | 33 | impl Error for ApiError { 34 | fn description(&self) -> &str { 35 | match *self { 36 | ApiError::NotFound => "Record not found", 37 | ApiError::InternalServerError => "Internal server error", 38 | } 39 | } 40 | } 41 | 42 | 43 | impl<'r> Responder<'r> for ApiError { 44 | fn respond_to(self, _request: &Request) -> Result, Status> { 45 | match self { 46 | ApiError::NotFound => Err(Status::NotFound), 47 | _ => Err(Status::InternalServerError), 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Chapter06/ch6/rocket-blog/src/main.rs: -------------------------------------------------------------------------------- 1 | #![feature(decl_macro)] 2 | 3 | #[macro_use] 4 | extern crate diesel; 5 | extern crate dotenv; 6 | extern crate serde_json; 7 | #[macro_use] 8 | extern crate lazy_static; 9 | #[macro_use] extern crate rocket; 10 | extern crate rocket_contrib; 11 | #[macro_use] 12 | extern crate serde_derive; 13 | extern crate r2d2; 14 | extern crate r2d2_diesel; 15 | 16 | mod schema; 17 | mod db; 18 | mod post; 19 | mod models; 20 | mod error; 21 | 22 | use db::DB; 23 | use post::{get_posts, get_post, create_post, delete_post, update_post}; 24 | use models::*; 25 | use rocket_contrib::json::Json; 26 | use rocket::response::status::{Created, NoContent}; 27 | use rocket::Rocket; 28 | use error::ApiError; 29 | 30 | #[get("/posts", format = "application/json")] 31 | fn posts_get(db: DB) -> Result>, ApiError> { 32 | let posts = get_posts(&db)?; 33 | Ok(Json(posts)) 34 | } 35 | 36 | #[get("/posts/", format = "application/json")] 37 | fn post_get(db: DB, id: i32) -> Result, ApiError> { 38 | let post = get_post(&db, id)?; 39 | Ok(Json(post)) 40 | } 41 | 42 | #[post("/posts", format = "json", data = "")] 43 | fn post_create(db: DB, post: PostData) -> Result, ApiError> { 44 | let post = create_post(&db, post); 45 | let url = format!("/post/{}", post); 46 | Ok(Created(url, Some("Done".to_string()))) 47 | } 48 | 49 | #[patch("/posts/", format = "application/json", data = "")] 50 | fn post_edit(db: DB, id: i32, post: PostData) -> Result, ApiError> { 51 | let post = update_post(&db, id, post); 52 | Ok(Json(post)) 53 | } 54 | 55 | #[delete("/posts/")] 56 | fn post_delete(db: DB, id: i32) -> Result { 57 | delete_post(&db, id)?; 58 | Ok(NoContent) 59 | } 60 | 61 | fn rocket() -> Rocket { 62 | rocket::ignite().mount("/", routes![post_create, posts_get, post_delete, post_edit, post_get]) 63 | } 64 | 65 | fn main() { 66 | rocket().launch(); 67 | } 68 | -------------------------------------------------------------------------------- /Chapter06/ch6/rocket-blog/src/models.rs: -------------------------------------------------------------------------------- 1 | use super::schema::posts; 2 | use rocket::{Request, Data}; 3 | use rocket::data::{FromDataSimple, Outcome}; 4 | use rocket::http::{Status, ContentType}; 5 | use rocket::Outcome::*; 6 | use serde_json; 7 | use std::io::Read; 8 | 9 | #[derive(Queryable)] 10 | #[derive(Serialize,Deserialize)] 11 | pub struct Post { 12 | pub id: i32, 13 | pub title: String, 14 | pub body: String, 15 | pub pinned: bool, 16 | } 17 | 18 | #[derive(Insertable, Deserialize, AsChangeset, Debug, Default)] 19 | #[table_name="posts"] 20 | pub struct PostData { 21 | pub title: String, 22 | pub body: String, 23 | pub pinned: bool, 24 | } 25 | 26 | impl FromDataSimple for PostData { 27 | type Error = String; 28 | 29 | #[allow(unused_variables)] 30 | fn from_data(req: &Request, data: Data) -> Outcome { 31 | let person_ct = ContentType::new("application", "json"); 32 | if req.content_type() != Some(&person_ct) { 33 | return Outcome::Forward(data); 34 | } 35 | let mut buffer = String::new(); 36 | let reader = data.open().read_to_string(&mut buffer); 37 | 38 | match serde_json::from_str::(&buffer) { 39 | Ok(pd) => Success(pd), 40 | Err(e) => Failure((Status::BadRequest, e.to_string())), 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Chapter06/ch6/rocket-blog/src/post.rs: -------------------------------------------------------------------------------- 1 | use diesel::result::Error; 2 | use diesel; 3 | use diesel::sqlite::SqliteConnection; 4 | use models::*; 5 | use diesel::prelude::*; 6 | use schema::posts; 7 | 8 | pub fn get_post(conn: &SqliteConnection, id: i32) -> Result { 9 | posts::table 10 | .find(id) 11 | .first::(conn) 12 | } 13 | 14 | pub fn get_posts(conn: &SqliteConnection) -> Result, Error> { 15 | posts::table 16 | .load::(conn) 17 | } 18 | 19 | pub fn create_post(conn: &SqliteConnection, post: PostData) -> bool { 20 | diesel::insert_into(posts::table).values(&post).execute(conn).is_ok() 21 | } 22 | 23 | pub fn delete_post(conn: &SqliteConnection, id: i32) -> Result { 24 | diesel::delete(posts::table.find(id)) 25 | .execute(conn) 26 | } 27 | 28 | pub fn update_post(conn: &SqliteConnection, id: i32, updated_post: PostData) -> bool { 29 | diesel::update(posts::table 30 | .find(id)) 31 | .set(&updated_post).execute(conn).is_ok() 32 | } 33 | -------------------------------------------------------------------------------- /Chapter06/ch6/rocket-blog/src/schema.rs: -------------------------------------------------------------------------------- 1 | table! { 2 | posts (id) { 3 | id -> Integer, 4 | title -> Text, 5 | body -> Text, 6 | pinned -> Bool, 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Chapter06/ch6/rocket-simple/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter06/ch6/rocket-simple/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rocket-simple" 3 | version = "0.1.0" 4 | authors = ["Foo "] 5 | 6 | [dependencies] 7 | rocket = "0.3.6" 8 | rocket_codegen = "0.3.6" 9 | -------------------------------------------------------------------------------- /Chapter06/ch6/rocket-simple/src/main.rs: -------------------------------------------------------------------------------- 1 | #![feature(plugin)] 2 | #![plugin(rocket_codegen)] 3 | 4 | extern crate rocket; 5 | 6 | #[get("/")] 7 | fn blast_off() -> &'static str { 8 | "Hello, Rocket!" 9 | } 10 | 11 | fn main() { 12 | rocket::ignite().mount("/", routes![blast_off]).launch(); 13 | } 14 | -------------------------------------------------------------------------------- /Chapter06/ch6/rocket-templates/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter06/ch6/rocket-templates/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Foo"] 3 | name = "rocket-templates" 4 | version = "0.1.0" 5 | 6 | [dependencies] 7 | rocket = "0.3.5" 8 | rocket_codegen = "0.3.5" 9 | 10 | [dependencies.rocket_contrib] 11 | version = "*" 12 | default-features = false 13 | features = ["tera_templates"] 14 | -------------------------------------------------------------------------------- /Chapter06/ch6/rocket-templates/src/main.rs: -------------------------------------------------------------------------------- 1 | #![feature(plugin)] 2 | #![plugin(rocket_codegen)] 3 | 4 | extern crate rocket_contrib; 5 | extern crate rocket; 6 | 7 | use rocket_contrib::Template; 8 | use rocket::{Rocket, State}; 9 | use std::collections::HashMap; 10 | use std::sync::atomic::{AtomicUsize, Ordering}; 11 | 12 | struct VisitorCounter { 13 | visitor_number: AtomicUsize, 14 | } 15 | 16 | #[get("/webpage/")] 17 | fn webpage(name: String, visitor: State) -> Template { 18 | let mut context = HashMap::new(); 19 | context.insert("name", name); 20 | let current = visitor.visitor_number.fetch_add(1, Ordering::SeqCst); 21 | context.insert("visitor_number", current.to_string()); 22 | Template::render("webpage", &context) 23 | } 24 | 25 | fn rocket() -> Rocket { 26 | rocket::ignite() 27 | .manage(VisitorCounter { visitor_number: AtomicUsize::new(1) }) 28 | .mount("/", routes![webpage]) 29 | .attach(Template::fairing()) 30 | } 31 | 32 | fn main() { 33 | rocket().launch(); 34 | } 35 | -------------------------------------------------------------------------------- /Chapter06/ch6/rocket-templates/templates/webpage.html.tera: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Rocket template demo 6 | 7 | 8 |

Hi {{name}}, you are visitor number {{ visitor_number }}

9 | 10 | 11 | -------------------------------------------------------------------------------- /Chapter07/collatz-client/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter07/collatz-client/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "collatz-client" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | futures = "0.1" 8 | tokio-core = "0.1" 9 | tokio-io = "0.1" 10 | -------------------------------------------------------------------------------- /Chapter07/collatz-client/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate futures; 2 | extern crate tokio_core; 3 | extern crate tokio_io; 4 | 5 | use std::net::SocketAddr; 6 | use std::io::BufReader; 7 | use futures::Future; 8 | use tokio_core::reactor::Core; 9 | use tokio_core::net::TcpStream; 10 | 11 | fn main() { 12 | let mut core = Core::new().expect("Could not create event loop"); 13 | let handle = core.handle(); 14 | let addr: SocketAddr = "127.0.0.1:9999".parse().expect("Could not parse as SocketAddr"); 15 | let socket = TcpStream::connect(&addr, &handle); 16 | let request = socket.and_then(|socket| { 17 | tokio_io::io::write_all(socket, b"110\n") 18 | }); 19 | let response = request.and_then(|(socket, _request)| { 20 | let sock = BufReader::new(socket); 21 | tokio_io::io::read_until(sock, b'\n', Vec::new()) 22 | }); 23 | let (_socket, data) = core.run(response).unwrap(); 24 | println!("{}", String::from_utf8_lossy(&data)); 25 | } 26 | -------------------------------------------------------------------------------- /Chapter07/collatz-multiplexed/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | Cargo.lock 5 | -------------------------------------------------------------------------------- /Chapter07/collatz-multiplexed/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "collatz-multiplexed" 3 | version = "0.1.0" 4 | authors = ["Foo "] 5 | 6 | [dependencies] 7 | bytes = "0.4" 8 | futures = "0.1" 9 | tokio-io = "0.1" 10 | tokio-core = "0.1" 11 | tokio-proto = "0.1" 12 | tokio-service = "0.1" 13 | -------------------------------------------------------------------------------- /Chapter07/collatz-multiplexed/examples/client.rs: -------------------------------------------------------------------------------- 1 | extern crate collatz_multiplexed as collatz; 2 | 3 | extern crate futures; 4 | extern crate tokio_core; 5 | extern crate tokio_service; 6 | 7 | use futures::Future; 8 | use tokio_core::reactor::Core; 9 | use tokio_service::Service; 10 | 11 | pub fn main() { 12 | let addr = "127.0.0.1:9999".parse().unwrap(); 13 | let mut core = Core::new().unwrap(); 14 | let handle = core.handle(); 15 | 16 | core.run( 17 | collatz::Client::connect(&addr, &handle) 18 | .and_then(|client| { 19 | client.call("110".to_string()) 20 | .and_then(move |response| { 21 | println!("We got back: {:?}", response); 22 | Ok(()) 23 | }) 24 | }) 25 | ).unwrap(); 26 | } 27 | -------------------------------------------------------------------------------- /Chapter07/collatz-multiplexed/examples/server.rs: -------------------------------------------------------------------------------- 1 | extern crate collatz_multiplexed as collatz; 2 | 3 | extern crate tokio_proto; 4 | 5 | use tokio_proto::TcpServer; 6 | 7 | use collatz::{CollatzService, CollatzProto}; 8 | 9 | fn main() { 10 | let addr = "0.0.0.0:9999".parse().unwrap(); 11 | TcpServer::new(CollatzProto, addr).serve(|| Ok(CollatzService)); 12 | } 13 | -------------------------------------------------------------------------------- /Chapter07/collatz-multiplexed/src/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate bytes; 2 | extern crate futures; 3 | extern crate tokio_core; 4 | extern crate tokio_io; 5 | extern crate tokio_proto; 6 | extern crate tokio_service; 7 | 8 | use futures::{future, Future}; 9 | 10 | use tokio_io::{AsyncRead, AsyncWrite}; 11 | use tokio_io::codec::{Decoder, Encoder, Framed}; 12 | use tokio_core::net::TcpStream; 13 | use tokio_core::reactor::Handle; 14 | use tokio_proto::TcpClient; 15 | use tokio_proto::multiplex::{ClientProto, ClientService, RequestId, ServerProto}; 16 | use tokio_service::Service; 17 | 18 | use bytes::{BigEndian, Buf, BufMut, BytesMut}; 19 | 20 | use std::{io, str}; 21 | use std::net::SocketAddr; 22 | 23 | // Everything client side 24 | pub struct Client { 25 | inner: ClientService, 26 | } 27 | 28 | impl Client { 29 | pub fn connect( 30 | addr: &SocketAddr, 31 | handle: &Handle, 32 | ) -> Box> { 33 | let ret = TcpClient::new(CollatzProto) 34 | .connect(addr, handle) 35 | .map(|service| Client { 36 | inner: service, 37 | }); 38 | 39 | Box::new(ret) 40 | } 41 | } 42 | 43 | impl Service for Client { 44 | type Request = String; 45 | type Response = String; 46 | type Error = io::Error; 47 | type Future = Box>; 48 | 49 | fn call(&self, req: String) -> Self::Future { 50 | Box::new(self.inner.call(req).and_then(move |resp| Ok(resp))) 51 | } 52 | } 53 | 54 | // Everything server side 55 | pub struct CollatzCodec; 56 | pub struct CollatzProto; 57 | type CollatzFrame = (RequestId, String); 58 | 59 | impl Decoder for CollatzCodec { 60 | type Item = CollatzFrame; 61 | type Error = io::Error; 62 | 63 | fn decode(&mut self, buf: &mut BytesMut) -> Result, io::Error> { 64 | if buf.len() < 5 { 65 | return Ok(None); 66 | } 67 | 68 | let newline = buf[4..].iter().position(|b| *b == b'\n'); 69 | if let Some(n) = newline { 70 | let line = buf.split_to(n + 4); 71 | buf.split_to(1); 72 | let request_id = io::Cursor::new(&line[0..4]).get_u32::(); 73 | return match str::from_utf8(&line.as_ref()[4..]) { 74 | Ok(s) => Ok(Some((u64::from(request_id), s.to_string()))), 75 | Err(_) => Err(io::Error::new(io::ErrorKind::Other, "invalid string")), 76 | }; 77 | } 78 | 79 | Ok(None) 80 | } 81 | } 82 | 83 | impl Encoder for CollatzCodec { 84 | type Item = CollatzFrame; 85 | type Error = io::Error; 86 | 87 | fn encode(&mut self, msg: CollatzFrame, buf: &mut BytesMut) -> io::Result<()> { 88 | let len = 4 + msg.1.len() + 1; 89 | buf.reserve(len); 90 | 91 | let (request_id, msg) = msg; 92 | 93 | buf.put_u32::(request_id as u32); 94 | buf.put_slice(msg.as_bytes()); 95 | buf.put_u8(b'\n'); 96 | 97 | Ok(()) 98 | } 99 | } 100 | 101 | impl ClientProto for CollatzProto { 102 | type Request = String; 103 | type Response = String; 104 | 105 | type Transport = Framed; 106 | type BindTransport = Result; 107 | 108 | fn bind_transport(&self, io: T) -> Self::BindTransport { 109 | Ok(io.framed(CollatzCodec)) 110 | } 111 | } 112 | 113 | impl ServerProto for CollatzProto { 114 | type Request = String; 115 | type Response = String; 116 | 117 | type Transport = Framed; 118 | type BindTransport = Result; 119 | 120 | fn bind_transport(&self, io: T) -> Self::BindTransport { 121 | Ok(io.framed(CollatzCodec)) 122 | } 123 | } 124 | 125 | pub struct CollatzService; 126 | 127 | fn get_sequence(mut n: u64) -> Vec { 128 | let mut result = vec![]; 129 | result.push(n); 130 | while n > 1 { 131 | if n % 2 == 0 { 132 | n /= 2; 133 | } else { 134 | n = 3 * n + 1; 135 | } 136 | result.push(n); 137 | } 138 | result 139 | } 140 | 141 | impl Service for CollatzService { 142 | type Request = String; 143 | type Response = String; 144 | type Error = io::Error; 145 | type Future = Box>; 146 | 147 | fn call(&self, req: Self::Request) -> Self::Future { 148 | match req.trim().parse::() { 149 | Ok(num) => { 150 | let res = get_sequence(num); 151 | Box::new(future::ok(format!("{:?}", res))) 152 | } 153 | Err(_) => Box::new(future::ok("Could not parse input as an u64".to_owned())), 154 | } 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /Chapter07/collatz-proto/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter07/collatz-proto/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "collatz-proto" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | bytes = "0.4" 8 | futures = "0.1" 9 | tokio-io = "0.1" 10 | tokio-core = "0.1" 11 | tokio-proto = "0.1" 12 | tokio-service = "0.1" -------------------------------------------------------------------------------- /Chapter07/collatz-proto/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate bytes; 2 | extern crate futures; 3 | extern crate tokio_io; 4 | extern crate tokio_proto; 5 | extern crate tokio_service; 6 | 7 | use std::io; 8 | use std::str; 9 | use bytes::BytesMut; 10 | use tokio_io::codec::{Decoder, Encoder}; 11 | use tokio_io::{AsyncRead, AsyncWrite}; 12 | use tokio_io::codec::Framed; 13 | use tokio_proto::pipeline::ServerProto; 14 | use tokio_service::Service; 15 | use futures::{future, Future}; 16 | use tokio_proto::TcpServer; 17 | 18 | // Codec implementation, our codec is a simple unit struct 19 | pub struct CollatzCodec; 20 | 21 | // Decoding a byte stream from the underlying socket 22 | impl Decoder for CollatzCodec { 23 | type Item = String; 24 | type Error = io::Error; 25 | 26 | fn decode(&mut self, buf: &mut BytesMut) -> io::Result> { 27 | // Since a newline denotes end of input, read till a newline 28 | if let Some(i) = buf.iter().position(|&b| b == b'\n') { 29 | let line = buf.split_to(i); 30 | // and remove the newline 31 | buf.split_to(1); 32 | // try to decode into an UTF8 string before passing to the protocol 33 | match str::from_utf8(&line) { 34 | Ok(s) => Ok(Some(s.to_string())), 35 | Err(_) => Err(io::Error::new(io::ErrorKind::Other, "invalid UTF-8")), 36 | } 37 | } else { 38 | Ok(None) 39 | } 40 | } 41 | } 42 | 43 | // Encoding a string to a newline terminated byte stream 44 | impl Encoder for CollatzCodec { 45 | type Item = String; 46 | type Error = io::Error; 47 | 48 | fn encode(&mut self, msg: String, buf: &mut BytesMut) -> io::Result<()> { 49 | buf.extend(msg.as_bytes()); 50 | buf.extend(b"\n"); 51 | Ok(()) 52 | } 53 | } 54 | 55 | // Protocol implementation as an unit struct 56 | pub struct CollatzProto; 57 | 58 | impl ServerProto for CollatzProto { 59 | type Request = String; 60 | type Response = String; 61 | type Transport = Framed; 62 | type BindTransport = Result; 63 | fn bind_transport(&self, io: T) -> Self::BindTransport { 64 | Ok(io.framed(CollatzCodec)) 65 | } 66 | } 67 | 68 | // Service implementation 69 | pub struct CollatzService; 70 | 71 | fn get_sequence(n: u64) -> Vec { 72 | let mut n = n.clone(); 73 | let mut result = vec![]; 74 | result.push(n); 75 | while n > 1 { 76 | if n % 2 == 0 { 77 | n /= 2; 78 | } else { 79 | n = 3 * n + 1; 80 | } 81 | result.push(n); 82 | } 83 | result 84 | } 85 | 86 | impl Service for CollatzService { 87 | type Request = String; 88 | type Response = String; 89 | type Error = io::Error; 90 | type Future = Box>; 91 | 92 | fn call(&self, req: Self::Request) -> Self::Future { 93 | match req.trim().parse::() { 94 | Ok(num) => { 95 | let res = get_sequence(num); 96 | Box::new(future::ok(format!("{:?}", res))) 97 | } 98 | Err(_) => Box::new(future::ok("Could not parse input as an u64".to_owned())), 99 | } 100 | } 101 | } 102 | 103 | fn main() { 104 | let addr = "0.0.0.0:9999".parse().unwrap(); 105 | let server = TcpServer::new(CollatzProto, addr); 106 | server.serve(|| Ok(CollatzService)); 107 | } 108 | -------------------------------------------------------------------------------- /Chapter07/collatz-streaming/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "collatz-streaming" 3 | version = "0.1.0" 4 | authors = ["Foo "] 5 | 6 | [dependencies] 7 | bytes = "0.4" 8 | futures = "0.1" 9 | tokio-io = "0.1" 10 | tokio-core = "0.1" 11 | tokio-proto = "0.1" 12 | tokio-service = "0.1" 13 | -------------------------------------------------------------------------------- /Chapter07/collatz-streaming/examples/client.rs: -------------------------------------------------------------------------------- 1 | extern crate collatz_streaming as collatz; 2 | 3 | extern crate futures; 4 | extern crate tokio_core; 5 | extern crate tokio_service; 6 | 7 | use collatz::{CollatzInput, CollatzStream}; 8 | use std::thread; 9 | use futures::Sink; 10 | use futures::Future; 11 | use tokio_core::reactor::Core; 12 | use tokio_service::Service; 13 | 14 | pub fn main() { 15 | let addr = "127.0.0.1:9999".parse().unwrap(); 16 | let mut core = Core::new().unwrap(); 17 | let handle = core.handle(); 18 | 19 | core.run( 20 | collatz::Client::connect(&addr, &handle) 21 | .and_then(|client| { 22 | client.call(CollatzInput::Once("10".to_string())) 23 | .and_then(move |response| { 24 | println!("Response: {:?}", response); 25 | 26 | let (mut tx, rx) = CollatzStream::pair(); 27 | 28 | thread::spawn(move || { 29 | for msg in &["Hello", "world", "!"] { 30 | tx = tx.send(Ok(msg.to_string())).wait().unwrap(); 31 | } 32 | }); 33 | 34 | client.call(CollatzInput::Stream(rx)) 35 | }) 36 | .and_then(|response| { 37 | println!("Response: {:?}", response); 38 | Ok(()) 39 | }) 40 | }) 41 | ).unwrap(); 42 | } 43 | -------------------------------------------------------------------------------- /Chapter07/collatz-streaming/examples/server.rs: -------------------------------------------------------------------------------- 1 | extern crate collatz_streaming as collatz; 2 | extern crate futures; 3 | 4 | extern crate tokio_proto; 5 | 6 | use tokio_proto::TcpServer; 7 | use collatz::{CollatzProto, CollatzService}; 8 | 9 | fn main() { 10 | let addr = "0.0.0.0:9999".parse().unwrap(); 11 | TcpServer::new(CollatzProto, addr).serve(|| Ok(CollatzService)); 12 | } 13 | -------------------------------------------------------------------------------- /Chapter07/futures-bilock/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter07/futures-bilock/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "futures-bilock" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | futures = "0.1" 8 | rand = "0.3.18" 9 | -------------------------------------------------------------------------------- /Chapter07/futures-bilock/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate futures; 2 | extern crate rand; 3 | 4 | use std::thread; 5 | use std::fmt::Debug; 6 | use std::time::Duration; 7 | use futures::{Future, Async}; 8 | use rand::{thread_rng, Rng}; 9 | 10 | use futures::sync::{mpsc, BiLock}; 11 | use futures::{Sink, Stream}; 12 | use futures::sync::mpsc::Receiver; 13 | 14 | fn sender(send: &BiLock) -> &'static str { 15 | match send.poll_lock() { 16 | Async::Ready(mut lock) => *lock += 1, 17 | Async::NotReady => () 18 | } 19 | let mut d = thread_rng(); 20 | thread::sleep(Duration::from_secs(d.gen_range::(1, 5))); 21 | d.choose(&["ping", "pong"]).unwrap() 22 | } 23 | 24 | fn receiver(recv: Receiver, recv_lock: BiLock) { 25 | match recv_lock.poll_lock() { 26 | Async::Ready(lock) => println!("Value of lock {}", *lock), 27 | Async::NotReady => () 28 | } 29 | let f = recv.for_each(|item| { 30 | println!("{:?}", item); 31 | Ok(()) 32 | }); 33 | f.wait().ok(); 34 | } 35 | 36 | fn main() { 37 | let counter = 0; 38 | let (send, recv) = BiLock::new(counter); 39 | let (tx, rx) = mpsc::channel(100); 40 | let h1 = thread::spawn(move || { 41 | tx.send(sender(&send)).wait().ok(); 42 | }); 43 | let h2 = thread::spawn(|| { 44 | receiver::<&str>(rx, recv); 45 | }); 46 | h1.join().unwrap(); 47 | h2.join().unwrap(); 48 | } 49 | -------------------------------------------------------------------------------- /Chapter07/futures-chaining/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter07/futures-chaining/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "futures-chaining" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | tokio-timer = "0.1.2" 8 | futures = "0.1.17" 9 | futures-cpupool = "0.1.7" 10 | rand = "*" -------------------------------------------------------------------------------- /Chapter07/futures-chaining/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate futures; 2 | extern crate futures_cpupool; 3 | extern crate tokio_timer; 4 | extern crate rand; 5 | 6 | use futures::future::select_ok; 7 | use std::time::Duration; 8 | 9 | use futures::Future; 10 | use futures_cpupool::CpuPool; 11 | use tokio_timer::Timer; 12 | use std::thread; 13 | use rand::{thread_rng, Rng}; 14 | 15 | fn player_one() -> &'static str { 16 | let d = thread_rng().gen_range::(1, 5); 17 | thread::sleep(Duration::from_secs(d)); 18 | "player_one" 19 | } 20 | 21 | fn player_two() -> &'static str { 22 | let d = thread_rng().gen_range::(1, 5); 23 | thread::sleep(Duration::from_secs(d)); 24 | "player_two" 25 | } 26 | 27 | fn main() { 28 | let pool = CpuPool::new_num_cpus(); 29 | let timer = Timer::default(); 30 | 31 | let timeout = timer.sleep(Duration::from_secs(3)) 32 | .then(|_| Err(())); 33 | 34 | let one = pool.spawn_fn(|| { 35 | Ok(player_one()) 36 | }); 37 | 38 | let two = pool.spawn_fn(|| { 39 | Ok(player_two()) 40 | }); 41 | 42 | let tasks = vec![one, two]; 43 | let winner = select_ok(tasks).select(timeout).map(|(result, _)| result); 44 | let result = winner.wait().ok(); 45 | match result { 46 | Some(("player_one", _)) => println!("Player one won"), 47 | Some(("player_two", _)) => println!("Player two won"), 48 | Some((_, _)) | None => println!("Timed out"), 49 | } 50 | } -------------------------------------------------------------------------------- /Chapter07/futures-example/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter07/futures-example/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "futures-example" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | futures = "0.1.17" 8 | futures-cpupool = "0.1.7" -------------------------------------------------------------------------------- /Chapter07/futures-example/src/main.rs: -------------------------------------------------------------------------------- 1 | #![feature(conservative_impl_trait)] 2 | extern crate futures; 3 | extern crate futures_cpupool; 4 | 5 | use std::io; 6 | use futures::Future; 7 | use futures_cpupool::CpuPool; 8 | 9 | fn check_prime_boxed(n: u64) -> Box> { 10 | for i in 2..n { 11 | if n % i == 0 { return Box::new(futures::future::ok(false)); } 12 | } 13 | Box::new(futures::future::ok(true)) 14 | } 15 | 16 | fn check_prime_impl_trait(n: u64) -> impl Future { 17 | for i in 2..n { 18 | if n % i == 0 { return futures::future::ok(false); } 19 | } 20 | futures::future::ok(true) 21 | } 22 | 23 | fn check_prime(n: u64) -> bool { 24 | for i in 2..n { 25 | if n % i == 0 { return false } 26 | } 27 | true 28 | } 29 | 30 | fn main() { 31 | let input: u64 = 58466453; 32 | println!("Right before first call"); 33 | let res_one = check_prime_boxed(input); 34 | println!("Called check_prime_boxed"); 35 | let res_two = check_prime_impl_trait(input); 36 | let r = futures::executor::spawn(res_one); 37 | println!("Called check_prime_impl_trait"); 38 | println!("Results are {} and {}", res_one.wait().unwrap(), res_two.wait().unwrap()); 39 | 40 | let thread_pool = CpuPool::new(4); 41 | let res_three = thread_pool.spawn_fn(move || { 42 | let temp = check_prime(input); 43 | let result: Result = Ok(temp); 44 | result 45 | }); 46 | println!("Called check_prime in another thread"); 47 | println!("Result from the last call: {}", res_three.wait().unwrap()); 48 | } 49 | -------------------------------------------------------------------------------- /Chapter07/futures-loop/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter07/futures-loop/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "futures-loop" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | futures = "0.1" 8 | tokio-core = "0.1" -------------------------------------------------------------------------------- /Chapter07/futures-loop/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate futures; 2 | extern crate tokio_core; 3 | 4 | use std::io; 5 | use std::io::BufRead; 6 | use futures::Future; 7 | use tokio_core::reactor::Core; 8 | 9 | fn check_prime_boxed(n: u64) -> Box> { 10 | for i in 2..n { 11 | if n % i == 0 { 12 | return Box::new(futures::future::ok(false)); 13 | } 14 | } 15 | Box::new(futures::future::ok(true)) 16 | } 17 | 18 | fn main() { 19 | let mut core = Core::new().expect("Could not create event loop"); 20 | let stdin = io::stdin(); 21 | 22 | loop { 23 | let mut line = String::new(); 24 | stdin 25 | .lock() 26 | .read_line(&mut line) 27 | .expect("Could not read from stdin"); 28 | let input = line.trim() 29 | .parse::() 30 | .expect("Could not parse input as u64"); 31 | let result = core.run(check_prime_boxed(input)) 32 | .expect("Could not run future"); 33 | println!("{}", result); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Chapter07/futures-ping-pong/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter07/futures-ping-pong/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "futures-ping-pong" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | futures = "0.1" 8 | tokio-core = "0.1" 9 | rand = "0.3.18" 10 | -------------------------------------------------------------------------------- /Chapter07/futures-ping-pong/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate futures; 2 | extern crate rand; 3 | extern crate tokio_core; 4 | 5 | use std::thread; 6 | use std::fmt::Debug; 7 | use std::time::Duration; 8 | use futures::Future; 9 | use rand::{thread_rng, Rng}; 10 | 11 | use futures::sync::mpsc; 12 | use futures::{Sink, Stream}; 13 | use futures::sync::mpsc::Receiver; 14 | 15 | fn sender() -> &'static str { 16 | let mut d = thread_rng(); 17 | thread::sleep(Duration::from_secs(d.gen_range::(1, 5))); 18 | d.choose(&["ping", "pong"]).unwrap() 19 | } 20 | 21 | fn receiver(recv: Receiver) { 22 | let f = recv.for_each(|item| { 23 | println!("{:?}", item); 24 | Ok(()) 25 | }); 26 | f.wait().ok(); 27 | } 28 | 29 | fn main() { 30 | let (tx, rx) = mpsc::channel(100); 31 | let h1 = thread::spawn(|| { 32 | tx.send(sender()).wait().ok(); 33 | }); 34 | let h2 = thread::spawn(|| { 35 | receiver::<&str>(rx); 36 | }); 37 | h1.join().unwrap(); 38 | h2.join().unwrap(); 39 | } 40 | -------------------------------------------------------------------------------- /Chapter07/streams/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter07/streams/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "streams" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | futures = "0.1.17" 8 | rand = "0.3.18" -------------------------------------------------------------------------------- /Chapter07/streams/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate futures; 2 | extern crate rand; 3 | 4 | use std::{io, thread}; 5 | use std::time::Duration; 6 | use futures::stream::Stream; 7 | use futures::{Poll, Async}; 8 | use rand::{thread_rng, Rng}; 9 | use futures::Future; 10 | 11 | #[derive(Debug)] 12 | struct CollatzStream { 13 | current: u64, 14 | end: u64, 15 | } 16 | 17 | impl CollatzStream { 18 | fn new(start: u64) -> CollatzStream { 19 | CollatzStream { 20 | current: start, 21 | end: 1 22 | } 23 | } 24 | } 25 | 26 | impl Stream for CollatzStream { 27 | type Item = u64; 28 | type Error = io::Error; 29 | fn poll(&mut self) -> Poll, io::Error> { 30 | let d = thread_rng().gen_range::(1, 5); 31 | thread::sleep(Duration::from_secs(d)); 32 | if self.current % 2 == 0 { 33 | self.current = self.current / 2; 34 | } else { 35 | self.current = 3 * self.current + 1; 36 | } 37 | if self.current == self.end { 38 | Ok(Async::Ready(None)) 39 | } else { 40 | Ok(Async::Ready(Some(self.current))) 41 | } 42 | } 43 | } 44 | 45 | fn main() { 46 | let stream = CollatzStream::new(10); 47 | let f = stream.for_each(|num| { 48 | println!("{}", num); 49 | Ok(()) 50 | }); 51 | f.wait().ok(); 52 | } -------------------------------------------------------------------------------- /Chapter07/tokio-curl/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter07/tokio-curl/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tokio-curl" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | tokio-curl = "0.1" 8 | tokio-core = "0.1" 9 | curl = "0.4.8" 10 | -------------------------------------------------------------------------------- /Chapter07/tokio-curl/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate curl; 2 | extern crate tokio_core; 3 | extern crate tokio_curl; 4 | 5 | use curl::easy::Easy; 6 | use tokio_core::reactor::Core; 7 | use tokio_curl::Session; 8 | use std::io::Write; 9 | use std::fs::File; 10 | 11 | fn main() { 12 | let mut core = Core::new().unwrap(); 13 | let session = Session::new(core.handle()); 14 | 15 | let mut handle = Easy::new(); 16 | let mut file = File::create("foo.zip").unwrap(); 17 | handle.get(true).unwrap(); 18 | handle.url("http://ipv4.download.thinkbroadband.com/5MB.zip").unwrap(); 19 | handle.header_function(|header| { 20 | print!("{}", std::str::from_utf8(header).unwrap()); 21 | true 22 | }).unwrap(); 23 | handle.write_function(move |data| { 24 | file.write_all(data).unwrap(); 25 | Ok(data.len()) 26 | }).unwrap(); 27 | 28 | let request = session.perform(handle); 29 | 30 | let mut response = core.run(request).unwrap(); 31 | println!("{:?}", response.response_code()); 32 | } 33 | -------------------------------------------------------------------------------- /Chapter08/key-exchange/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | Cargo.lock 5 | -------------------------------------------------------------------------------- /Chapter08/key-exchange/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "key-exchange" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | ring = "0.12.1" 8 | untrusted = "0.5.1" 9 | 10 | -------------------------------------------------------------------------------- /Chapter08/key-exchange/examples/client.rs: -------------------------------------------------------------------------------- 1 | extern crate ring; 2 | extern crate untrusted; 3 | 4 | use std::net::TcpStream; 5 | use std::io::{BufRead, BufReader, Write}; 6 | 7 | use ring::{agreement, rand}; 8 | use untrusted::Input; 9 | 10 | fn main() { 11 | let mut stream = TcpStream::connect("127.0.0.1:8888").expect("Could not connect to server"); 12 | 13 | let rng = rand::SystemRandom::new(); 14 | let client_private_key = agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng).expect("Failed to generate key"); 15 | let mut client_public_key = [0u8; agreement::PUBLIC_KEY_MAX_LEN]; 16 | let client_public_key = &mut client_public_key[..client_private_key.public_key_len()]; 17 | client_private_key.compute_public_key(client_public_key).expect("Failed to generate key"); 18 | 19 | stream.write(client_public_key).expect("Failed to write to server"); 20 | 21 | let mut buffer: Vec = Vec::new(); 22 | let mut reader = BufReader::new(&stream); 23 | reader.read_until(b'\n', &mut buffer).expect("Could not read into buffer"); 24 | let peer_public_key = Input::from(&buffer); 25 | 26 | println!("Received: {:?}", peer_public_key); 27 | 28 | let res = agreement::agree_ephemeral(client_private_key, &agreement::X25519, peer_public_key, ring::error::Unspecified, 29 | |key_material| { 30 | let mut key = Vec::new(); 31 | key.extend_from_slice(key_material); 32 | Ok(key) 33 | }); 34 | 35 | println!("Generated: {:?}", res.unwrap()); 36 | } 37 | -------------------------------------------------------------------------------- /Chapter08/key-exchange/examples/server.rs: -------------------------------------------------------------------------------- 1 | extern crate ring; 2 | extern crate untrusted; 3 | 4 | use std::net::{TcpListener, TcpStream}; 5 | use std::thread; 6 | use std::io::{Read, Write}; 7 | 8 | use ring::{agreement, rand}; 9 | use untrusted::Input; 10 | use ring::error::Unspecified; 11 | 12 | fn handle_client(mut stream: TcpStream) -> Result<(), Unspecified> { 13 | let rng = rand::SystemRandom::new(); 14 | 15 | let server_private_key = agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng)?; 16 | let mut server_public_key = [0u8; agreement::PUBLIC_KEY_MAX_LEN]; 17 | let server_public_key = &mut server_public_key[..server_private_key.public_key_len()]; 18 | server_private_key.compute_public_key(server_public_key)?; 19 | 20 | let mut peer_public_key_buf = [0u8; 32]; 21 | stream.read(&mut peer_public_key_buf).expect("Failed to read"); 22 | let peer_public_key = Input::from(&peer_public_key_buf); 23 | 24 | println!("Received: {:?}", peer_public_key); 25 | 26 | stream.write(&server_public_key).expect("Failed to send server public key"); 27 | 28 | let res = agreement::agree_ephemeral(server_private_key, &agreement::X25519, peer_public_key, ring::error::Unspecified, 29 | |key_material| { 30 | let mut key = Vec::new(); 31 | key.extend_from_slice(key_material); 32 | Ok(key) 33 | }); 34 | 35 | println!("Generated: {:?}", res.unwrap()); 36 | 37 | Ok(()) 38 | } 39 | 40 | fn main() { 41 | let listener = TcpListener::bind("0.0.0.0:8888").expect("Could not bind"); 42 | for stream in listener.incoming() { 43 | match stream { 44 | Err(e) => { eprintln!("failed: {}", e) } 45 | Ok(stream) => { 46 | thread::spawn(move || { 47 | handle_client(stream).unwrap_or_else(|error| eprintln!("{:?}", error)); 48 | }); 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Chapter08/key-exchange/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | #[test] 4 | fn it_works() { 5 | assert_eq!(2 + 2, 4); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Chapter08/openssl-example/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter08/openssl-example/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "bitflags" 3 | version = "1.0.1" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | 6 | [[package]] 7 | name = "cc" 8 | version = "1.0.3" 9 | source = "registry+https://github.com/rust-lang/crates.io-index" 10 | 11 | [[package]] 12 | name = "foreign-types" 13 | version = "0.3.2" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | dependencies = [ 16 | "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 17 | ] 18 | 19 | [[package]] 20 | name = "foreign-types-shared" 21 | version = "0.1.1" 22 | source = "registry+https://github.com/rust-lang/crates.io-index" 23 | 24 | [[package]] 25 | name = "lazy_static" 26 | version = "1.0.0" 27 | source = "registry+https://github.com/rust-lang/crates.io-index" 28 | 29 | [[package]] 30 | name = "libc" 31 | version = "0.2.35" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | 34 | [[package]] 35 | name = "openssl" 36 | version = "0.9.23" 37 | source = "git+https://github.com/sfackler/rust-openssl#71862e976910382eaac91b3994026b07c7ea98fc" 38 | dependencies = [ 39 | "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 40 | "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", 41 | "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 42 | "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", 43 | "openssl-sys 0.9.23 (git+https://github.com/sfackler/rust-openssl)", 44 | ] 45 | 46 | [[package]] 47 | name = "openssl-example" 48 | version = "0.1.0" 49 | dependencies = [ 50 | "openssl 0.9.23 (git+https://github.com/sfackler/rust-openssl)", 51 | ] 52 | 53 | [[package]] 54 | name = "openssl-sys" 55 | version = "0.9.23" 56 | source = "git+https://github.com/sfackler/rust-openssl#71862e976910382eaac91b3994026b07c7ea98fc" 57 | dependencies = [ 58 | "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 59 | "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", 60 | "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 61 | "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 62 | ] 63 | 64 | [[package]] 65 | name = "pkg-config" 66 | version = "0.3.9" 67 | source = "registry+https://github.com/rust-lang/crates.io-index" 68 | 69 | [[package]] 70 | name = "vcpkg" 71 | version = "0.2.2" 72 | source = "registry+https://github.com/rust-lang/crates.io-index" 73 | 74 | [metadata] 75 | "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" 76 | "checksum cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b13a57efd6b30ecd6598ebdb302cca617930b5470647570468a65d12ef9719" 77 | "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 78 | "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 79 | "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" 80 | "checksum libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)" = "96264e9b293e95d25bfcbbf8a88ffd1aedc85b754eba8b7d78012f638ba220eb" 81 | "checksum openssl 0.9.23 (git+https://github.com/sfackler/rust-openssl)" = "" 82 | "checksum openssl-sys 0.9.23 (git+https://github.com/sfackler/rust-openssl)" = "" 83 | "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" 84 | "checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b" 85 | -------------------------------------------------------------------------------- /Chapter08/openssl-example/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "openssl-example" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | openssl = { git = "https://github.com/sfackler/rust-openssl" } 8 | 9 | -------------------------------------------------------------------------------- /Chapter08/openssl-example/foo.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIID2jCCAkKgAwIBAgIUVqB+7JbI4z6DaRuAgB9j29lMmwswDQYJKoZIhvcNAQEN 3 | BQAwJzELMAkGA1UEBhMCVUsxGDAWBgNVBAMMD091ciBjb21tb24gbmFtZTAeFw0x 4 | ODAxMDYyMzEyMTZaFw0xOTAxMDYyMzEyMTZaMCcxCzAJBgNVBAYTAlVLMRgwFgYD 5 | VQQDDA9PdXIgY29tbW9uIG5hbWUwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGK 6 | AoIBgQC26SmLRZjhVmRTdrEQvOAGN2QPbkaNE0d0qEkYeY9QFRiYYQpVQZU4gsB9 7 | iz2kljHb5zsOFfc5o2Dsroe2e26XuMLAD0V6YMJb9t5nMoC2FHB4fEhWEkUcz10z 8 | wf9JAspHYUZa8tutMx5AyEGMPxkZRoLG1Qq/XSEKPdQZSnc37B1HJEAkPQt+QyhL 9 | XC8ryyY1MHj06Pfb16HsaZAkLFK52t9hnfe/GeInkOXKorshxpK99CDNFliSY9S/ 10 | x7BrI5vX7270W9O+GVjkaiWZyxqLJQutLziRxY1RDUunCSvzthxbatzdhxjNCSJH 11 | noX/HKLpkr4E0TVN1NfdM8x2XQi1hhe0gUItH/8/syWVyqSHWD/9u7R5iSm77j5H 12 | ifbi+m98PookRf6nL8M6wh+23wVD+EBqIVM7ZlnlznR0KHDkj+qJFXQ6IHNjlYTz 13 | plk2tAYnB44JbcqIYxRfo21o6ZM5uYvh45rd223A0zj5Vvmr6EuEuNP1AtkXXcjG 14 | 19/j/w8CAwEAATANBgkqhkiG9w0BAQ0FAAOCAYEAjOZRR14Qt6IJO7HR6vSMZFdx 15 | 913oKgDrHfpxkEUMqi+9+Wowe0MgVg4jRwh+ybVfGAhr/eongDyh/KGLtK7M+ACa 16 | P9THNI2xREHx9IeE0ir1CMeO4n7LgsJnTyGJTyigaaQ0r3MR1utlCqMHo9NQI5PA 17 | jSGJt7lgccXfSnlaJAsv8D97WdELbJQd/Uy+ooqIyr7yRW1DTSeUn89pBLAmuaCP 18 | 9nOHMNLHptPGJDYQTt9vVZmAtrY20FdMlVqfBn9AK3F9aKy4ixvgIyymVOzETyYM 19 | AiPhOQs8CmthPDt5UthGp5Mh8aFEcM6Sbjok3LlyDNOPsB+z8Nqy2vfV8tEkRN+t 20 | V3ZPyk4qhZJhn1Wr1TwXNVBqncSZg8Od1zyHmUEUkGDhK05NgQdPKw7/JFoT4cxD 21 | 2DJI2a8lG0jqMODu0fWXRlWt2+mqj0YLo9En96yyF+PQLDu+5ikPKDPjFd7ZgntQ 22 | 3cXtuILXbzFQjPbaSdvy+g6e/f08YJ4vLsHmuu4L 23 | -----END CERTIFICATE----- 24 | -------------------------------------------------------------------------------- /Chapter08/openssl-example/server.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICjTCCAfYCCQCJQLPaKNP/dzANBgkqhkiG9w0BAQsFADCBijELMAkGA1UEBhMC 3 | VUsxEDAOBgNVBAgMB0VuZ2xhbmQxDzANBgNVBAcMBkxvbmRvbjEPMA0GA1UECgwG 4 | Rm9vYmFyMRQwEgYDVQQLDAtFbmdpbmVlcmluZzEVMBMGA1UEAwwMbXkuZG9tYWlu 5 | LmlvMRowGAYJKoZIhvcNAQkBFgtmb29AYmFyLmNvbTAeFw0xODAxMDUyMTUyMTJa 6 | Fw0xOTAxMDUyMTUyMTJaMIGKMQswCQYDVQQGEwJVSzEQMA4GA1UECAwHRW5nbGFu 7 | ZDEPMA0GA1UEBwwGTG9uZG9uMQ8wDQYDVQQKDAZGb29iYXIxFDASBgNVBAsMC0Vu 8 | Z2luZWVyaW5nMRUwEwYDVQQDDAxteS5kb21haW4uaW8xGjAYBgkqhkiG9w0BCQEW 9 | C2Zvb0BiYXIuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8xW9UmHCQ 10 | 84Fy3MFDWNn2/SQq6aQ5D3yjYz6YkW7WCcUkoeU3AeionYTkM169WjirA3WCgxiD 11 | ugwSriJNpsEF/t1WIt3BgZ3YIQp8tq6SOep9d/4EsmPabcZF0Urx4VO214yk5m/v 12 | JQyGKdo6VgkAV0gjCLmyaj9DHqGyyrJZvQIDAQABMA0GCSqGSIb3DQEBCwUAA4GB 13 | ABqcyI7iGTbsD15a9xp2byaiRB7X/lwaDhNVIV6mgpzXwy6svGHLw4SJ6B4KiAF+ 14 | LEbQuqEt489H2OmhCR9qf/n0/CsX6YDdLe507+7GXV+9XIlLyGxsv7H5Sib0cYjL 15 | prYm8pCVyTAXySMJ8yGDugELqujHbGSnaV9rRr/VqIWC 16 | -----END CERTIFICATE----- 17 | -------------------------------------------------------------------------------- /Chapter08/openssl-example/server.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIByzCCATQCAQAwgYoxCzAJBgNVBAYTAlVLMRAwDgYDVQQIDAdFbmdsYW5kMQ8w 3 | DQYDVQQHDAZMb25kb24xDzANBgNVBAoMBkZvb2JhcjEUMBIGA1UECwwLRW5naW5l 4 | ZXJpbmcxFTATBgNVBAMMDG15LmRvbWFpbi5pbzEaMBgGCSqGSIb3DQEJARYLZm9v 5 | QGJhci5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALzFb1SYcJDzgXLc 6 | wUNY2fb9JCrppDkPfKNjPpiRbtYJxSSh5TcB6KidhOQzXr1aOKsDdYKDGIO6DBKu 7 | Ik2mwQX+3VYi3cGBndghCny2rpI56n13/gSyY9ptxkXRSvHhU7bXjKTmb+8lDIYp 8 | 2jpWCQBXSCMIubJqP0MeobLKslm9AgMBAAGgADANBgkqhkiG9w0BAQsFAAOBgQBo 9 | V8ee9lAarYdop0r99X5Fz+RiEdlfn0/GvObgj520iwNYiNJCkVnw0F9KircsQPfd 10 | 5W952K2KBqIjBiJQmN1J+wOzheQ8PdpOyfMSlVMYlJT94YzNWFOsmBut7N2d8n02 11 | jjPtBNndyGrMJ3Opg4x1q71hw1ks75gdcsxMvXpccA== 12 | -----END CERTIFICATE REQUEST----- 13 | -------------------------------------------------------------------------------- /Chapter08/openssl-example/server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXAIBAAKBgQC8xW9UmHCQ84Fy3MFDWNn2/SQq6aQ5D3yjYz6YkW7WCcUkoeU3 3 | AeionYTkM169WjirA3WCgxiDugwSriJNpsEF/t1WIt3BgZ3YIQp8tq6SOep9d/4E 4 | smPabcZF0Urx4VO214yk5m/vJQyGKdo6VgkAV0gjCLmyaj9DHqGyyrJZvQIDAQAB 5 | AoGAeGcRyIpmmf3G3kVxu4wLkl8J15kolwCKxggCH/v7DugyZ1gfxEMia5H09jzR 6 | u8K1DFbrd7A4TaS4GJ4a4R5wVFMusXrwI5cYX32eHtq8cmiWi/CHaQlX/ucbiBAT 7 | KMVNmvM3uj2FiuihPmaYwlfl5JB1nfFPNx0Ixqic0I8TJx0CQQDfzCrS0lMK0rHW 8 | 61MRVY0d46YnQj0aJ14teW2qw4SzjTTGmR4Grhu2C4oaFdmyqCNCAXfOR4f5ZgSw 9 | JRP2v66PAkEA1+8I30NAN+XOC5IqzFIWH1ip/UH9QDMsy2EdVR743Tb0N6C/pPWg 10 | 28N476aIzAq/Y/ve8STOxw3m8CcbPJnY8wJAU1CgyKeAPtE9X7Nv0040IOJ1Irxo 11 | Hup1BxzjlOUA7A8vjJfIM9hxfI5DNX7Y8sfhiFsfjO3YUyKFsEW9bujhRQJBAJFv 12 | IV6eAOalFL2eWMz8jIHYScWVaGiRDx577jGihqMXnCzLS8hi11CsuwtN8tzacEV7 13 | IpDv5YUTy/L7o9CRHhkCQFSiOSFbe9LiND5pNxh95ZtK5P6HiDy+u/z94jpG72MR 14 | MToLKrle5WNT+V2ljn1FrX8fDBZeXepsGKRRT8AfXD8= 15 | -----END RSA PRIVATE KEY----- 16 | -------------------------------------------------------------------------------- /Chapter08/openssl-example/server.key.org: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | Proc-Type: 4,ENCRYPTED 3 | DEK-Info: DES-EDE3-CBC,9EBC2B07AC7C6E89 4 | 5 | bodlC6YB/yjNgXsZYFS1FGb6oSDtGzhBFQ2nv6CTKiFvYTIM9VcpWq+mhnhegIlR 6 | 3Gdixas4jaJLMAyBpc3eU0NbWgcHwe0cOQlNRbzExA8BVBNUNkCebSRwDHFdR9Wm 7 | A5x4DRT+/A5qoxh3vWSx5NEhG7Hw2sjh+CM3kb650U9zlhFBlcDzaoJdjXxMue3O 8 | U5kvYY51JFhRzyDLjI7/4dP3n4+72bxyQCLGC55L99DVXCahqZ+bwaYFFW2VJP9B 9 | WA+rENinpG7LCuaeBh08ZYh7IluElg1lzsIaz4unFilQlvT5rR6WIXl9IPLYpHqA 10 | zlRV4TJarFRjdpocoG6+n3txNiXCVUU5s7zOxO2i5QGaQgqKC5OciFDdVTyw6et3 11 | 0/3e4sqCPZCN37WecRxbEyDVroLKafenylNwBZHyGwmOs6HHaVGtWIAxheJFV6nj 12 | nBQ9XsQd1s856y7DiaoX2acv5+RbVfniGCTGrRnkdndV39og2IdSB3Hy5OCu3M0U 13 | 83gw4CVv7jrnwg+75FLKtIKJY+zqQYZoKurO2lp/eRPGn0wxKgchP1gjOv7ceii2 14 | pwFhlsL1JAeaIbMmoF3sdFDAsUf5PwLfrWPTvNn2JNxb6Catm0pJth+QKn47084E 15 | j6kuoVMQXNbk4ocb2HISnXEU0TipcUeY8GmExKOv34RTV9KUkrcFQoFtX/ZG1k4r 16 | 2EVFtfuj1T9/JNddzhsPHLBhz1mS7vOYglDVs+hv+zg0qlgTUagJ21gb7NOwZAF8 17 | Uxw8bL7Bamq9ir+NvG31QPTRljdKwGMHov2O8KMBXsv+eirAG33Jkg== 18 | -----END RSA PRIVATE KEY----- 19 | -------------------------------------------------------------------------------- /Chapter08/openssl-example/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate openssl; 2 | 3 | use std::env; 4 | use std::fs::File; 5 | use std::io::Write; 6 | 7 | use openssl::x509::{X509, X509Name}; 8 | use openssl::nid::Nid; 9 | use openssl::pkey::{PKey, Private}; 10 | use openssl::rsa::Rsa; 11 | use openssl::error::ErrorStack; 12 | use openssl::asn1::Asn1Time; 13 | use openssl::bn::{BigNum, MsbOption}; 14 | use openssl::hash::MessageDigest; 15 | 16 | fn create_cert() -> Result<(X509, PKey), ErrorStack> { 17 | let mut cert_builder = X509::builder()?; 18 | cert_builder.set_version(2)?; 19 | 20 | let serial_number = { 21 | let mut serial = BigNum::new()?; 22 | serial.rand(160, MsbOption::MAYBE_ZERO, false)?; 23 | serial.to_asn1_integer()? 24 | }; 25 | cert_builder.set_serial_number(&serial_number)?; 26 | 27 | let mut name = X509Name::builder()?; 28 | name.append_entry_by_text("C", "UK")?; 29 | name.append_entry_by_text("CN", "Our common name")?; 30 | let cert_name = name.build(); 31 | cert_builder.set_issuer_name(&cert_name)?; 32 | 33 | let not_before = Asn1Time::days_from_now(0)?; 34 | cert_builder.set_not_before(¬_before)?; 35 | 36 | let not_after = Asn1Time::days_from_now(365)?; 37 | cert_builder.set_not_after(¬_after)?; 38 | 39 | cert_builder.set_subject_name(&cert_name)?; 40 | 41 | let private_key = PKey::from_rsa(Rsa::generate(3072)?)?; 42 | cert_builder.set_pubkey(&private_key)?; 43 | 44 | cert_builder.sign(&private_key, MessageDigest::sha512())?; 45 | let cert = cert_builder.build(); 46 | 47 | Ok((cert, private_key)) 48 | } 49 | 50 | fn main() { 51 | if let Some(arg) = env::args().nth(1) { 52 | let (cert, _key) = create_cert().expect("could not create cert"); 53 | let cert_data = cert.to_pem().expect("could not convert cert to pem"); 54 | 55 | let mut cert_file = File::create(arg).expect("could not create cert file"); 56 | cert_file 57 | .write_all(&cert_data) 58 | .expect("failed to write cert"); 59 | 60 | let subject = cert.subject_name(); 61 | let cn = subject 62 | .entries_by_nid(Nid::COMMONNAME) 63 | .next() 64 | .expect("failed to get subject"); 65 | println!( 66 | "{}", 67 | String::from_utf8(cn.data().as_slice().to_vec()).unwrap() 68 | ); 69 | } else { 70 | eprintln!("Expected at least one argument"); 71 | std::process::exit(1); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Chapter08/openssl-example/test.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDXTCCAkWgAwIBAgIJAPZOZto3t3I6MA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV 3 | BAYTAlVLMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX 4 | aWRnaXRzIFB0eSBMdGQwHhcNMTgwMTA1MTg0MDQzWhcNMTkwMTA1MTg0MDQzWjBF 5 | MQswCQYDVQQGEwJVSzETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 6 | ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB 7 | CgKCAQEA12vk4Vu8GXNcLkdaORWsvP5M0ggwP0z3BG6y799fMp7uGmbkEKP4AeTg 8 | 4FJYPies2sj3NYcRp9MOarfGfzxiqWtwTL5ZUoUsffIyk8Hizdz9l/VetocjAZGq 9 | yJegtNNdJfz57egC1bizmleGPYbInkj9A6mIERY551ma8U4fRjjOVdg/GXxJFu/C 10 | XuMcPn4vG4SzEFg7PSMKt+NpfxD2c9jnkWtxNpBbnnAAItIz4WI7UH/sgo9MbHfe 11 | Xyfc+QMNGzQzxNSCoZcqnzdquO844btkPPe/3eXyjX2DC+iZIHvtjj89qk8a8uml 12 | 6xseywwoP10i7kND7GJ77xvK9FUFqQIDAQABo1AwTjAdBgNVHQ4EFgQUFr0Ia2UN 13 | oq/5P1+BQ7INNQ2fGDowHwYDVR0jBBgwFoAUFr0Ia2UNoq/5P1+BQ7INNQ2fGDow 14 | DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAabEeyWcEnGvsFL+leKns 15 | HqRxNKAR/Tkd0U0WKgBniALvG4nOR821L5PpQEiwJD0LTjtNaAMCR8YqMqZV/Vr1 16 | V5mb2zMqZyWmqwTXaRXwVrulrbTyfzMiMgXfl/UJqs8xBhR7jfdLeiPSewdN1OK2 17 | K8HG+oMZev93JU3x1JhHy9M60+F6YxDTYoA4ykx6SugyRoOn4DB+AXNR0hRKkOSK 18 | 5F+Z8cwTFDZlJGvB+Fv7YM77r0grwNGm+OVK7XFgSlgCnHOmjcGrHtzbV2sN+Gh1 19 | OFdFSC8c+/9B2aF2m1FmK1OCMoeMjfhXhWKPFYa8GLohKM+ZSUX+F7HBdQUCGOEq 20 | pw== 21 | -----END CERTIFICATE----- 22 | -------------------------------------------------------------------------------- /Chapter08/rustls-client/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter08/rustls-client/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rustls-client" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | rustls = "0.12.0" 8 | webpki = "0.18.0-alpha" 9 | webpki-roots = "0.14.0" 10 | -------------------------------------------------------------------------------- /Chapter08/rustls-client/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | 3 | use std::net::TcpStream; 4 | use std::io::{Read, Write}; 5 | 6 | extern crate rustls; 7 | extern crate webpki; 8 | extern crate webpki_roots; 9 | 10 | fn main() { 11 | let mut tls = rustls::ClientConfig::new(); 12 | tls.root_store.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS); 13 | 14 | let name = webpki::DNSNameRef::try_from_ascii_str("my.domain.io").expect("Could not resolve name"); 15 | let mut sess = rustls::ClientSession::new(&Arc::new(tls), name); 16 | let mut conn = TcpStream::connect("my.domain.io:8000").unwrap(); 17 | let mut stream = rustls::Stream::new(&mut sess, &mut conn); 18 | stream.write(concat!("GET / HTTP/1.1\r\n", 19 | "Connection: close\r\n", 20 | "\r\n") 21 | .as_bytes()) 22 | .expect("Could not write request"); 23 | let mut plaintext = Vec::new(); 24 | stream.read_to_end(&mut plaintext).expect("Could not read"); 25 | println!("{}", String::from_utf8(plaintext).expect("Could not print output")); 26 | } -------------------------------------------------------------------------------- /Chapter08/tokio-tls-example/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter08/tokio-tls-example/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tokio-tls-example" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | hyper = "0.11.7" 8 | futures = "0.1.17" 9 | net2 = "0.2.31" 10 | tokio-core = "0.1.10" 11 | num_cpus = "1.0" 12 | native-tls = "*" 13 | tokio-service = "*" 14 | tokio-proto = "*" 15 | tokio-tls = { version = "0.1", features = ["tokio-proto"] } 16 | -------------------------------------------------------------------------------- /Chapter08/tokio-tls-example/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFWTCCA0GgAwIBAgIJAPr/U3vxaqKqMA0GCSqGSIb3DQEBCwUAMEMxCzAJBgNV 3 | BAYTAlVLMREwDwYDVQQIDAhTY290bGFuZDEhMB8GA1UECgwYSW50ZXJuZXQgV2lk 4 | Z2l0cyBQdHkgTHRkMB4XDTE4MDEwNzE3MzUwMloXDTE5MDEwNzE3MzUwMlowQzEL 5 | MAkGA1UEBhMCVUsxETAPBgNVBAgMCFNjb3RsYW5kMSEwHwYDVQQKDBhJbnRlcm5l 6 | dCBXaWRnaXRzIFB0eSBMdGQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC 7 | AQCh0mw9qQjecVL87TbNo3KD7iOhdQoJmxR5Qr529SJShqTg3XRHQgztZRCbVdj2 8 | 2H0csQAQPw+bTQens+wVHLrqbf9xOuP9L5WVLJD86qv0R0MsAqb25qsnb6+lZGna 9 | jz+sAu6+mmr0aSEYgjTSyVvIGpPJt1uuCRAXOcOKpi/mnKB0QIgTC4xZfYYb+Vgg 10 | FrVkW69SNxJwL/+9OhTPPuDL5tBOI7DC072WVHHVrNZU6/l1D/iX9j7NXR/xEHI1 11 | waymKj1sd6Z5z97UwKGSsroaZ71CkvpASDOL4ahfPobZX/49qarLcJkB5uuKilS6 12 | P5v6UH2ZNvMSypCYzb1I6eZjcfad4jgSorgwXdcqReIMndu3kH6TESN07NVtRzCM 13 | LhVB1na3uo4k4QvNDKCH1ft9aVSUQyg9NHeNyqFNH1BmQbgw15Df+WAg5vXFvbM2 14 | rGC28ADo8uvEkFLeYs0A45DmZd2e32ygtivXE1of+aj+vDLpp7kNXEyEHSYIf9NJ 15 | RtCr0xBbLwtCKMSQS/ci/iuinoAd1moqWLTJT+HHL0MMxo5W/QuZRc+l2/JM4FUG 16 | UQ4vxg11U09FjV7etORjn73zRsufyDXgjZ/YfwuD3odF+owAsUd+ZGEKA3oA0Qkg 17 | 17WLzMMPlsf2nnmbrc6o4DSZ5fpfBFbWyteZBE0tf89NHQIDAQABo1AwTjAdBgNV 18 | HQ4EFgQU5GOASgR5owHOJdnlq9lc85D2+PUwHwYDVR0jBBgwFoAU5GOASgR5owHO 19 | Jdnlq9lc85D2+PUwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEANQ7B 20 | gA8fjeuc8EuVhvLjipMi6yNVyrpMXkVs7R8h5Btrzcgn1WVYQHy645yxUUuHHvPU 21 | FdpL/7zj0Px1cgaMyJhZoxSmRmk7cZRW8+awQQhk0qekp6sp8louLjwKxDmkYWuh 22 | HKFSey4XalFEQQ49/RttBZvbmgOr/DbssMaX0s3BFXHHazU2qKar6xwbBJ5RWcC4 23 | 9PfZCp/OSvq+ZHEfQbE53Dch+9e78H+9z5R469E50mxQGYsxtsZ+uYY2Mq3WaGur 24 | 61C/i2FZUOHkz946JcljLPxvl/VVZIJlePmAEN81Pv0QaGayx8UTgdKasSTDN7kj 25 | md1w/YNK7Ptp8Cx9StfulGupO5PT6JpBriEYwJcm53aRW6N7fXI0NuIQ/e2IIfyQ 26 | aBygh/WaAWmmg5/HdF9i7Lp3xnKbY5zovu4841yJkaxrSqTkFSemcbAYLHhm0CSh 27 | wB6FfrBFGSVdNp1EmQmu5ZSHEy9StvxQ47uq3E3ylocAcctgm3n+zCaQ0bIwLAWq 28 | Pm2D+5IqZEfesuwuG5UYaMMDnSp/+hZVccexw3PSpHDj/g80QVzINsR7Vdy2crcX 29 | YZUZ6iKfkE9TNbhdjhspINRmYC4B7jrhATz0Sz9DIVHTSmP6FcebYjCnYHnfw3xK 30 | yEEKGnC84luGq67bFmrMJcpWtnlZdi+x0OfqFIo= 31 | -----END CERTIFICATE----- 32 | -------------------------------------------------------------------------------- /Chapter08/tokio-tls-example/cert.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Network-Programming-with-Rust/74f3650024ce3dd772300699beaa0059e2f30795/Chapter08/tokio-tls-example/cert.pfx -------------------------------------------------------------------------------- /Chapter08/tokio-tls-example/key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN ENCRYPTED PRIVATE KEY----- 2 | MIIJjjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIsImw6AH1EYYCAggA 3 | MBQGCCqGSIb3DQMHBAhoBX/wTkJjBQSCCUh37wIhgidRsrYzV03OXUimf5BJUhhR 4 | 4RRiy4z05pF8IcmbVPkb1VNbS3FS7SVL7QVBpaq0eisUCsIQXEvLg45+xXZhZNo8 5 | eLckB7k5N/+Kj4ypdbEL3leGLvDJM+ogJzUCuE50DusF5FE6CMI1EIS9RL3uE0zw 6 | L/6LGOmwdPZTQr686+vhhgBMNUB1/BvojBBdgsUKcHr30CYNu9hgWkAv00+TUXxa 7 | xByYtTBluae2eBpQ8AMxgjKrM5Sb6TlK3ISmPyMwLPUoTsb0MHceyC26yYCxIfD7 8 | GIC4IHwPuyCowfcizJ52XQsTQCHLaY1+5T8jKeHgGSNVBw2spc3FYFx9l1ZE4UWq 9 | S+4czkfOKVB8SpxBR6xv7QLDEfi8KodHWWNUUMuGUg8kJyIp7Ajpn7H0oOo6Z06i 10 | 4d4kwqfhckmiu9MmNC3FHKgCNK//aOd7s1xKWAhhD6BKa3Dv5Ta3ozfI7uv+jwn1 11 | boe16oCCUZYASJoXK0o42JmvqRkEGFURXr6+/GIfOzSBWjyA5fljH09W5SL11w/S 12 | WQljg47fpIBY0hBDV4CatkVEbTE+h6f7v9yoSzYdTiALLMvIgGIV6Qtaj0debbpr 13 | 6X4YGig+5btPNxC3/mvOYhDaFwrAPU4bIJRAPbMrOZ4u26pGw4jHqXXc4WmC/z0i 14 | 75k5wrL7wMSLW/0wiCri2dpSlQahbJaiOOxaToMOO/KMUHSNY1ZUH+d3+MoCJNtO 15 | 1NksOLUnPqwgGXTHX2A4FXKHEER930YHgIOFVJe64rAZaLI/PzhCrnrWoVUgZ/e8 16 | mMVYDb6VlOuF/yhe/t0i0OxZCckAMM+SSg3LTUcnmaGbjJGU7lV2KO2ExbZ7g6Py 17 | 12vwyUsDX0ZaGoHLo+z0xaRcGjSjV/glWjOlZyjSssTjBmfxju3ZzWVfOy2K9F1Q 18 | 9SUJ3A8+dXOvP4lsLBfg9UdXIFMpGYj86IAyFnOKTk0NDap9UWI/dKkXuBgjOg/e 19 | r1ulJX254XqOyPG0Tkq5lFxRyk6Wavcfs8PGTnie1lQqXkP32W7iPNJOxYA4qRrp 20 | 9ffLHNEw8yAYjndyd/DE0lzwG7nJhofsx/2Rk78q15cI0W0rzoz+4lou5QXddmd6 21 | HlIyA8mqSoDmptH/kONRhO8Etjynu7OhuBcTQbImFFP0zDnNt1C/uGuUeP8sqgAl 22 | zbgRLl7i5fvE1d44WaC9N6ZctRkzV62DvJDfqIUo6NXvTiUphr3ApBRADdjV9sZG 23 | AZ9EfuyH+B8063tZ7I1XfxDP9roPAmGhK4hAY2TZEqCDWPdG0CMSuuA/aaRrMfKm 24 | 9kroWip7FCxPch8c5S0068pb8K6dcvdDE2EuvwxpI0jI42LW8Q+AykmclPMwdyrI 25 | Nw9weFgggLoSVcpEnJZRY1iD1HcuABtpJRMLHCRWZUoJXbCd/fuzhQEY1ftz8I1H 26 | bnDUBlSw4JkWnTsQBSOWJ/xLho1S9XVwPh+TFT2rT7uV5iI/MhEoz2Fm4kqCvUZg 27 | 6LSjd18BLRwe16tqoLBOVJ+xjDl1XJWmb9JtXvzidCdnntZcLwbkDKzUqhwJQ7GQ 28 | jA31SkUMoC1USRxzXfKSLlGnz49elGgMmZlpU9l8K9alSQ8mk8Dm0ihVTVc9Vx4n 29 | wxbnzJyLCTf3Mgt4805o1dIJilXodjWOSg4bv3Pdvv+iEgQw72W7IOgIbwS4RPsy 30 | /rrrTKH6gEMbAa34UQ6DpEI0wpl3uJ86KFN1l0j1/XOTypiUt4gT280Yh81+/pwz 31 | rlKh5y2R9CFZim9fds8o3m8LhukLTftU3iIHSF9860YXXhcpT16ZskjTZZYiVa2M 32 | mLb7w69mmYLBYnMipBjs11TUDYz7b/wZuFrikGFxBJMUowgrLzjmn7HwWvPkaFDC 33 | OkxAiMTVSwt1TUdUaK7rq+7hKJK6h1UCTmVRUP4AACOs469NnfU5a2yfAaeLv62X 34 | VcOb3thUA4Aw0P/NRGnHMnmTKlr0q2QHlfcHJKlpau+yVArnMmufm3MAJaf2Ajc+ 35 | M/wUe1ujXwXCB6WXWTMpf3VFLfg/lojjcRhnmu9bY+scQmiEQKyPeTbxts3XanVl 36 | iuQ8rJPZL2UX74NspjQRlM9zQ76laNNcEzKgseM5um5J+oRNB3qfr7NGi5OFPE94 37 | wQoY/SH9P12Eh4WPTZZxV1Hjny9gmyfT9SIiofq6EAScRBqM6RF34OEyL/rvTXbq 38 | vBOLB0Q5UuAUYUn5nLrxVfcx9CzSaMhoRmPu/EIxcp8uGkNnkZx2WXecl9CWgYJV 39 | wPleczviUZ7VnnVcAZp99z1stDiTSglZq9b/3tJh+kmYr4oilzJxntks+x7HBV59 40 | MwkKAe1rcZa6rm7hn5v/6hENbhf3XixKSvwsLM8gZVxuMvdTossmmIBVeQVbSbki 41 | VnbOfGO/cAvSRbandv9QnibY1N7y8XJfuxv9BXaEAIRCgS2Yn+hFmQlVTXEtNn1L 42 | M2EA7tfpJO7KAsbPsUc9QrcEs+kl5BbRiVPKeKIF1Q1n5AvV5IGb29Pu6MGL7dh2 43 | Q8msxmMyjiJ2pb1ypUe/xG7OKE26Feh46obG/0ayMO4JECAo7v/QyFPoimtklr0F 44 | n1k2oL1d7W1KvZyg+P2shYVKc6RGjYsDs6xEXR1nrz65PjjLE0opn+7ohZH0q0uN 45 | BnzpfaJMgpMURQrW5OB7M0CJECWLC1CQvGs1H/JHc3GXQEhgcbTa4UFoxN3+NVsl 46 | xoHLpjc3GOeD6VMeucFwUmhyfxje7xzpJwKpJLdemgwHURFLZnc9rAPuIRKSmNJw 47 | veNSIEkeg4S72PMQbOpENwwipZdUyRGDohMFAG0Jt8sAAjAocTGpI/d1lFY/fZU0 48 | jpGpKPMceqViCd5YSGlZPC3bFXMOJiIVMIX5TOFdwJK39bJG7KMwdtY8C12RU16m 49 | UsaAzJCFxckug5qqfDzNR/oBTgvv/fs+DziFZX2H9d8TiSn5JS3rPDXlW3SUKkLC 50 | mo9+4ITTk2nFhYfKiKY/ut6SeTCdlHWoSw2pzd62adAFyKfK3wioBSrL6Z0Q1uGO 51 | iNVuQX0rvF1qAobej9pyoy+KYq8fwHTDp2YjXMLUXfO2Jlo3gl3D5vTCZYEYVdSr 52 | /E3u2K6HtCYP2b5ePKHa8Hseq6Jht9Cx/RfXVWKZ8G7+iSC1y/MCDTz0JVfi5SwH 53 | MeM= 54 | -----END ENCRYPTED PRIVATE KEY----- 55 | -------------------------------------------------------------------------------- /Chapter08/tokio-tls-example/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate futures; 2 | extern crate hyper; 3 | extern crate native_tls; 4 | extern crate tokio_proto; 5 | extern crate tokio_service; 6 | extern crate tokio_tls; 7 | 8 | use std::io; 9 | use std::{thread, time}; 10 | use futures::future::{ok, Future}; 11 | use hyper::server::Http; 12 | use hyper::header::ContentLength; 13 | use hyper::{Request, Response, StatusCode}; 14 | use native_tls::{Pkcs12, TlsAcceptor}; 15 | use tokio_proto::TcpServer; 16 | use tokio_service::Service; 17 | use tokio_tls::proto; 18 | 19 | fn heavy_work() -> String { 20 | let duration = time::Duration::from_millis(100); 21 | thread::sleep(duration); 22 | "done".to_string() 23 | } 24 | 25 | struct SlowMo; 26 | 27 | impl Service for SlowMo { 28 | type Request = Request; 29 | type Response = Response; 30 | type Error = io::Error; 31 | type Future = Box>; 32 | 33 | fn call(&self, req: Request) -> Self::Future { 34 | let b = heavy_work().into_bytes(); 35 | println!("Request: {:?}", req); 36 | Box::new(ok(Response::new() 37 | .with_status(StatusCode::Ok) 38 | .with_header(ContentLength(b.len() as u64)) 39 | .with_body(b))) 40 | } 41 | } 42 | 43 | fn main() { 44 | let raw_cert = include_bytes!("../cert.pfx"); 45 | let cert = Pkcs12::from_der(raw_cert, "foobar").unwrap(); 46 | let acceptor = TlsAcceptor::builder(cert).unwrap().build().unwrap(); 47 | let proto = proto::Server::new(Http::new(), acceptor); 48 | let addr = "0.0.0.0:9999".parse().unwrap(); 49 | let srv = TcpServer::new(proto, addr); 50 | println!("Listening on {}", addr); 51 | srv.serve(|| Ok(SlowMo)); 52 | } 53 | -------------------------------------------------------------------------------- /Chapter09/appendix/bitflags-example/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter09/appendix/bitflags-example/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "bitflags" 3 | version = "1.0.1" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | 6 | [[package]] 7 | name = "bitflags-example" 8 | version = "0.1.0" 9 | dependencies = [ 10 | "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 11 | ] 12 | 13 | [metadata] 14 | "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" 15 | -------------------------------------------------------------------------------- /Chapter09/appendix/bitflags-example/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bitflags-example" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | bitflags = "1.0" 8 | -------------------------------------------------------------------------------- /Chapter09/appendix/bitflags-example/src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate bitflags; 3 | 4 | bitflags! { 5 | struct Flags: u32 { 6 | const X = 0b00000001; 7 | const Y = 0b00000010; 8 | } 9 | } 10 | 11 | pub trait Format { 12 | fn decimal(&self); 13 | } 14 | 15 | impl Format for Flags { 16 | fn decimal(&self) { 17 | println!("Decimal: {}", self.bits()); 18 | } 19 | } 20 | 21 | fn main() { 22 | let flags = Flags::X | Flags::Y; 23 | flags.decimal(); 24 | (Flags::X | Flags::Y).decimal(); 25 | (Flags::Y).decimal(); 26 | 27 | println!("Current state: {:?}", Flags::all()); 28 | println!("Contains X? {:?}", flags.contains(Flags::X)); 29 | } 30 | -------------------------------------------------------------------------------- /Chapter09/appendix/collatz-generator/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter09/appendix/collatz-generator/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "collatz-generator" 3 | version = "0.1.0" 4 | 5 | -------------------------------------------------------------------------------- /Chapter09/appendix/collatz-generator/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "collatz-generator" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /Chapter09/appendix/collatz-generator/src/main.rs: -------------------------------------------------------------------------------- 1 | #![feature(generators, generator_trait)] 2 | 3 | use std::ops::{Generator, GeneratorState}; 4 | use std::env; 5 | 6 | fn main() { 7 | let input = env::args() 8 | .nth(1) 9 | .expect("Please provide only one argument") 10 | .parse::() 11 | .expect("Could not convert input to integer"); 12 | 13 | let mut generator = || { 14 | let end = 1u64; 15 | let mut current: u64 = input; 16 | while current != end { 17 | yield current; 18 | if current % 2 == 0 { 19 | current /= 2; 20 | } else { 21 | current = 3 * current + 1; 22 | } 23 | } 24 | return end; 25 | }; 26 | 27 | loop { 28 | match generator.resume() { 29 | GeneratorState::Yielded(el) => println!("{}", el), 30 | GeneratorState::Complete(el) => { 31 | println!("{}", el); 32 | break; 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Chapter09/appendix/collatz-may/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter09/appendix/collatz-may/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "collatz-may" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | may = "0.2.0" 8 | generator = "0.6" 9 | -------------------------------------------------------------------------------- /Chapter09/appendix/collatz-may/src/main.rs: -------------------------------------------------------------------------------- 1 | #![feature(conservative_impl_trait)] 2 | 3 | #[macro_use] 4 | extern crate generator; 5 | #[macro_use] 6 | extern crate may; 7 | 8 | use std::env; 9 | use generator::Gn; 10 | 11 | fn collatz_generator(start: u64) -> impl Iterator { 12 | Gn::new_scoped(move |mut s| { 13 | let end = 1u64; 14 | let mut current: u64 = start; 15 | while current != end { 16 | s.yield_(current); 17 | if current % 2 == 0 { 18 | current /= 2; 19 | } else { 20 | current = 3 * current + 1; 21 | } 22 | } 23 | s.yield_(end); 24 | done!(); 25 | }) 26 | } 27 | 28 | fn collatz(start: u64) -> Vec { 29 | let end = 1u64; 30 | let mut current: u64 = start; 31 | let mut result = Vec::new(); 32 | while current != end { 33 | result.push(current); 34 | if current % 2 == 0 { 35 | current /= 2; 36 | } else { 37 | current = 3 * current + 1; 38 | } 39 | } 40 | result.push(end); 41 | result 42 | } 43 | 44 | fn main() { 45 | let input = env::args() 46 | .nth(1) 47 | .expect("Please provide only one argument") 48 | .parse::() 49 | .expect("Could not convert input to integer"); 50 | go!(move || { 51 | println!("{:?}", collatz(input)); 52 | }).join() 53 | .unwrap(); 54 | 55 | let results = collatz_generator(input); 56 | for result in results { 57 | println!("{}", result); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Chapter09/appendix/hyper-async-await/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter09/appendix/hyper-async-await/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hyper-server-faster" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | hyper = "0.11.7" 8 | futures = "0.1.17" 9 | net2 = "0.2.31" 10 | tokio-core = "0.1.10" 11 | num_cpus = "1.0" 12 | futures-await = "0.1.0" 13 | -------------------------------------------------------------------------------- /Chapter09/appendix/hyper-async-await/src/main.rs: -------------------------------------------------------------------------------- 1 | #![feature(proc_macro, conservative_impl_trait, generators)] 2 | 3 | extern crate futures_await as futures; 4 | extern crate hyper; 5 | extern crate net2; 6 | extern crate tokio_core; 7 | extern crate num_cpus; 8 | 9 | use futures::prelude::*; 10 | use net2::unix::UnixTcpBuilderExt; 11 | use tokio_core::reactor::Core; 12 | use tokio_core::net::TcpListener; 13 | use std::{thread, time}; 14 | use std::net::SocketAddr; 15 | use std::sync::Arc; 16 | use hyper::{Get, StatusCode}; 17 | use hyper::header::ContentLength; 18 | use hyper::server::{Http, Service, Request, Response}; 19 | use futures::future::FutureResult; 20 | use std::io; 21 | 22 | fn heavy_work() -> String { 23 | let duration = time::Duration::from_millis(100); 24 | thread::sleep(duration); 25 | "done".to_string() 26 | } 27 | 28 | #[derive(Clone, Copy)] 29 | struct Echo; 30 | 31 | impl Service for Echo { 32 | type Request = Request; 33 | type Response = Response; 34 | type Error = hyper::Error; 35 | type Future = FutureResult; 36 | 37 | fn call(&self, req: Request) -> Self::Future { 38 | futures::future::ok(match (req.method(), req.path()) { 39 | (&Get, "/data") => { 40 | let b = heavy_work().into_bytes(); 41 | Response::new() 42 | .with_header(ContentLength(b.len() as u64)) 43 | .with_body(b) 44 | } 45 | _ => Response::new().with_status(StatusCode::NotFound), 46 | }) 47 | } 48 | } 49 | 50 | fn serve(addr: &SocketAddr, protocol: &Http) { 51 | let mut core = Core::new().unwrap(); 52 | let handle = core.handle(); 53 | let listener = net2::TcpBuilder::new_v4() 54 | .unwrap() 55 | .reuse_port(true) 56 | .unwrap() 57 | .bind(addr) 58 | .unwrap() 59 | .listen(128) 60 | .unwrap(); 61 | let listener = TcpListener::from_listener(listener, addr, &handle).unwrap(); 62 | let server = async_block! { 63 | #[async] 64 | for (socket, addr) in listener.incoming() { 65 | protocol.bind_connection(&handle, socket, addr, Echo); 66 | } 67 | Ok::<(), io::Error>(()) 68 | }; 69 | core.run(server).unwrap(); 70 | } 71 | 72 | fn start_server(num: usize, addr: &str) { 73 | let addr = addr.parse().unwrap(); 74 | 75 | let protocol = Arc::new(Http::new()); 76 | { 77 | for _ in 0..num - 1 { 78 | let protocol = Arc::clone(&protocol); 79 | thread::spawn(move || serve(&addr, &protocol)); 80 | } 81 | } 82 | serve(&addr, &protocol); 83 | } 84 | 85 | 86 | fn main() { 87 | start_server(num_cpus::get(), "0.0.0.0:3000"); 88 | } 89 | -------------------------------------------------------------------------------- /Chapter09/appendix/may-http/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter09/appendix/may-http/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "may-http" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | may_minihttp = { git = "https://github.com/Xudong-Huang/may_minihttp.git" } 8 | may = "0.2.0" 9 | num_cpus = "1.7.0" 10 | -------------------------------------------------------------------------------- /Chapter09/appendix/may-http/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate may; 2 | extern crate may_minihttp; 3 | extern crate num_cpus; 4 | 5 | use std::io; 6 | use may_minihttp::{HttpServer, HttpService, Request, Response}; 7 | use std::{thread, time}; 8 | 9 | fn heavy_work() -> String { 10 | let duration = time::Duration::from_millis(100); 11 | thread::sleep(duration); 12 | "done".to_string() 13 | } 14 | 15 | #[derive(Clone, Copy)] 16 | struct Echo; 17 | 18 | impl HttpService for Echo { 19 | fn call(&self, req: Request) -> io::Result { 20 | println!("Incoming request {:?}", req); 21 | let mut resp = Response::new(); 22 | match (req.method(), req.path()) { 23 | ("GET", "/data") => { 24 | let b = heavy_work(); 25 | resp.body(&b).status_code(200, "OK"); 26 | } 27 | (&_, _) => { 28 | resp.status_code(404, "Not found"); 29 | } 30 | } 31 | Ok(resp) 32 | } 33 | } 34 | 35 | fn main() { 36 | may::config().set_io_workers(num_cpus::get()); 37 | let server = HttpServer(Echo).start("0.0.0.0:3000").unwrap(); 38 | server.join().unwrap(); 39 | } 40 | -------------------------------------------------------------------------------- /Chapter09/appendix/pest-example/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter09/appendix/pest-example/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "pest" 3 | version = "1.0.3" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | 6 | [[package]] 7 | name = "pest-example" 8 | version = "0.1.0" 9 | dependencies = [ 10 | "pest 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 11 | "pest_derive 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 12 | ] 13 | 14 | [[package]] 15 | name = "pest_derive" 16 | version = "1.0.3" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | dependencies = [ 19 | "pest 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 20 | "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", 21 | "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", 22 | ] 23 | 24 | [[package]] 25 | name = "quote" 26 | version = "0.3.15" 27 | source = "registry+https://github.com/rust-lang/crates.io-index" 28 | 29 | [[package]] 30 | name = "syn" 31 | version = "0.11.11" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | dependencies = [ 34 | "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", 35 | "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", 36 | "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 37 | ] 38 | 39 | [[package]] 40 | name = "synom" 41 | version = "0.11.3" 42 | source = "registry+https://github.com/rust-lang/crates.io-index" 43 | dependencies = [ 44 | "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 45 | ] 46 | 47 | [[package]] 48 | name = "unicode-xid" 49 | version = "0.0.4" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | 52 | [metadata] 53 | "checksum pest 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1117ca38a751edc66a4cd9ca1b35644b7d00305971306e07e0d3befbc61e906" 54 | "checksum pest_derive 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1debf85717cb8fa6bf2aad21fbbe888fda5797aae22d332cefec9ba79b6c7a33" 55 | "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" 56 | "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" 57 | "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" 58 | "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" 59 | -------------------------------------------------------------------------------- /Chapter09/appendix/pest-example/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pest-example" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | pest = "^1.0" 8 | pest_derive = "^1.0" 9 | -------------------------------------------------------------------------------- /Chapter09/appendix/pest-example/src/grammar.pest: -------------------------------------------------------------------------------- 1 | newline = { "\n" } 2 | carriage_return = { "\r" } 3 | space = { " " } 4 | get = { "GET" } 5 | post = { "POST" } 6 | sep = { "/" } 7 | version = { "HTTP/1.1" } 8 | chars = { 'a'..'z' | 'A'..'Z' } 9 | request = { get | post } 10 | 11 | ident_list = _{ request ~ space ~ sep ~ chars+ ~ sep ~ space ~ version ~ carriage_return ~ newline } 12 | -------------------------------------------------------------------------------- /Chapter09/appendix/pest-example/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate pest; 2 | #[macro_use] 3 | extern crate pest_derive; 4 | 5 | use pest::Parser; 6 | 7 | #[derive(Parser)] 8 | #[grammar = "grammar.pest"] 9 | struct RequestParser; 10 | 11 | fn main() { 12 | let get = RequestParser::parse(Rule::ident_list, "GET /foobar/ HTTP/1.1\r\n") 13 | .unwrap_or_else(|e| panic!("{}", e)); 14 | for pair in get { 15 | println!("Rule: {:?}", pair.as_rule()); 16 | println!("Span: {:?}", pair.clone().into_span()); 17 | println!("Text: {}", pair.clone().into_span().as_str()); 18 | } 19 | 20 | let _ = RequestParser::parse(Rule::ident_list, "WRONG /foobar/ HTTP/1.1\r\n") 21 | .unwrap_or_else(|e| panic!("{}", e)); 22 | } 23 | -------------------------------------------------------------------------------- /Chapter09/appendix/rayon-parallel/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter09/appendix/rayon-parallel/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rayon-parallel" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | rayon = "0.9.0" 8 | rustc-test = "0.3.0" 9 | -------------------------------------------------------------------------------- /Chapter09/appendix/rayon-parallel/src/main.rs: -------------------------------------------------------------------------------- 1 | 2 | #![feature(test)] 3 | 4 | extern crate rayon; 5 | extern crate test; 6 | 7 | use rayon::prelude::*; 8 | 9 | fn filter_parallel(src: Vec) -> Vec { 10 | src.par_iter() 11 | .filter(|x| *x % 2 != 0) 12 | .map(|x| x * x) 13 | .collect() 14 | } 15 | 16 | 17 | fn filter_sequential(src: Vec) -> Vec { 18 | src.iter().filter(|x| *x % 2 != 0).map(|x| x * x).collect() 19 | } 20 | 21 | fn main() { 22 | let nums_one = (1..10).collect(); 23 | println!("{:?}", filter_sequential(nums_one)); 24 | 25 | let nums_two = (1..10).collect(); 26 | println!("{:?}", filter_parallel(nums_two)); 27 | } 28 | 29 | #[cfg(test)] 30 | mod tests { 31 | use super::*; 32 | use test::Bencher; 33 | 34 | #[bench] 35 | fn bench_filter_sequential(b: &mut Bencher) { 36 | b.iter(|| filter_sequential((1..1000).collect::>())); 37 | } 38 | 39 | #[bench] 40 | fn bench_filter_parallel(b: &mut Bencher) { 41 | b.iter(|| filter_parallel((1..1000).collect::>())); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Chapter09/appendix/rayon-search/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter09/appendix/rayon-search/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "bitflags" 3 | version = "1.0.1" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | 6 | [[package]] 7 | name = "coco" 8 | version = "0.1.1" 9 | source = "registry+https://github.com/rust-lang/crates.io-index" 10 | dependencies = [ 11 | "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 12 | "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 13 | ] 14 | 15 | [[package]] 16 | name = "either" 17 | version = "1.4.0" 18 | source = "registry+https://github.com/rust-lang/crates.io-index" 19 | 20 | [[package]] 21 | name = "fuchsia-zircon" 22 | version = "0.3.3" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | dependencies = [ 25 | "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 26 | "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 27 | ] 28 | 29 | [[package]] 30 | name = "fuchsia-zircon-sys" 31 | version = "0.3.3" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | 34 | [[package]] 35 | name = "lazy_static" 36 | version = "0.2.11" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | 39 | [[package]] 40 | name = "libc" 41 | version = "0.2.36" 42 | source = "registry+https://github.com/rust-lang/crates.io-index" 43 | 44 | [[package]] 45 | name = "num_cpus" 46 | version = "1.8.0" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | dependencies = [ 49 | "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", 50 | ] 51 | 52 | [[package]] 53 | name = "rand" 54 | version = "0.3.20" 55 | source = "registry+https://github.com/rust-lang/crates.io-index" 56 | dependencies = [ 57 | "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 58 | "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", 59 | ] 60 | 61 | [[package]] 62 | name = "rayon" 63 | version = "0.9.0" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | dependencies = [ 66 | "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 67 | "rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 68 | ] 69 | 70 | [[package]] 71 | name = "rayon-core" 72 | version = "1.3.0" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | dependencies = [ 75 | "coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 76 | "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 77 | "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", 78 | "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 79 | "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", 80 | ] 81 | 82 | [[package]] 83 | name = "rayon-search" 84 | version = "0.1.0" 85 | dependencies = [ 86 | "rayon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 87 | ] 88 | 89 | [[package]] 90 | name = "scopeguard" 91 | version = "0.3.3" 92 | source = "registry+https://github.com/rust-lang/crates.io-index" 93 | 94 | [metadata] 95 | "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" 96 | "checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd" 97 | "checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3" 98 | "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" 99 | "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" 100 | "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" 101 | "checksum libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121" 102 | "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" 103 | "checksum rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "512870020642bb8c221bf68baa1b2573da814f6ccfe5c9699b1c303047abe9b1" 104 | "checksum rayon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed02d09394c94ffbdfdc755ad62a132e94c3224a8354e78a1200ced34df12edf" 105 | "checksum rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e64b609139d83da75902f88fd6c01820046840a18471e4dfcd5ac7c0f46bea53" 106 | "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" 107 | -------------------------------------------------------------------------------- /Chapter09/appendix/rayon-search/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rayon-search" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | rayon = "0.9.0" -------------------------------------------------------------------------------- /Chapter09/appendix/rayon-search/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate rayon; 2 | 3 | use std::fmt::Debug; 4 | use rayon::scope; 5 | 6 | fn binary_search_rayon(src: &mut [T], el: T) -> bool { 7 | src.sort(); 8 | let mid = src.len() / 2; 9 | let srcmid = src[mid]; 10 | if src.len() == 1 && src[0] != el { 11 | return false; 12 | } 13 | if el == srcmid { 14 | true 15 | } else { 16 | let mut left_result = false; 17 | let mut right_result = false; 18 | let (left, right) = src.split_at_mut(mid); 19 | scope(|s| if el < srcmid { 20 | s.spawn(|_| left_result = binary_search_rayon(left, el)) 21 | } else { 22 | s.spawn(|_| right_result = binary_search_rayon(right, el)) 23 | }); 24 | left_result || right_result 25 | } 26 | } 27 | 28 | fn binary_search_recursive(src: &mut [T], el: T) -> bool { 29 | src.sort(); 30 | let mid = src.len() / 2; 31 | let srcmid = src[mid]; 32 | if src.len() == 1 && src[0] != el { 33 | return false; 34 | } 35 | if el == srcmid { 36 | true 37 | } else { 38 | let (left, right) = src.split_at_mut(mid); 39 | if el < srcmid { 40 | binary_search_recursive(left, el) 41 | } else { 42 | binary_search_recursive(right, el) 43 | } 44 | } 45 | } 46 | 47 | fn main() { 48 | let mut v = vec![100, 12, 121, 1, 23, 35]; 49 | println!("{}", binary_search_recursive(&mut v, 5)); 50 | println!("{}", binary_search_rayon(&mut v, 5)); 51 | println!("{}", binary_search_rayon(&mut v, 100)); 52 | } -------------------------------------------------------------------------------- /Chapter09/appendix/url-example/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Chapter09/appendix/url-example/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "idna" 3 | version = "0.1.4" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | dependencies = [ 6 | "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 7 | "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 8 | "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 9 | ] 10 | 11 | [[package]] 12 | name = "matches" 13 | version = "0.1.6" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | 16 | [[package]] 17 | name = "percent-encoding" 18 | version = "1.0.1" 19 | source = "registry+https://github.com/rust-lang/crates.io-index" 20 | 21 | [[package]] 22 | name = "unicode-bidi" 23 | version = "0.3.4" 24 | source = "registry+https://github.com/rust-lang/crates.io-index" 25 | dependencies = [ 26 | "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 27 | ] 28 | 29 | [[package]] 30 | name = "unicode-normalization" 31 | version = "0.1.5" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | 34 | [[package]] 35 | name = "url" 36 | version = "1.6.0" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | dependencies = [ 39 | "idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 40 | "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 41 | "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 42 | ] 43 | 44 | [[package]] 45 | name = "url-example" 46 | version = "0.1.0" 47 | dependencies = [ 48 | "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", 49 | ] 50 | 51 | [metadata] 52 | "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" 53 | "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" 54 | "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" 55 | "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" 56 | "checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" 57 | "checksum url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa35e768d4daf1d85733418a49fb42e10d7f633e394fccab4ab7aba897053fe2" 58 | -------------------------------------------------------------------------------- /Chapter09/appendix/url-example/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "url-example" 3 | version = "0.1.0" 4 | authors = ["Abhishek Chanda "] 5 | 6 | [dependencies] 7 | url = "1.6.0" -------------------------------------------------------------------------------- /Chapter09/appendix/url-example/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate url; 2 | 3 | use url::Url; 4 | 5 | fn main() { 6 | let url = Url::parse("git+https://foo:bar@gitlab.com/gitlab-org/gitlab-ce/blob/master/config/routes/development.rb#L8").unwrap(); 7 | println!("Scheme: {}", url.scheme()); 8 | println!("Username: {}", url.username()); 9 | println!("Password: {}", url.password().unwrap()); 10 | println!("Fragment: {}", url.fragment().unwrap()); 11 | println!("Host: {:?}", url.host().unwrap()); 12 | } 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # Network Programming with Rust 5 | This is the code repository for [Network Programming with Rust](https://www.packtpub.com/application-development/network-programming-rust?utm_source=github&utm_medium=repository&utm_campaign=9781788624893), published by [Packt](https://www.packtpub.com/?utm_source=github). It contains all the supporting project files necessary to work through the book from start to finish. 6 | ## About the Book 7 | Rust is low-level enough to provide fine-grained control over memory while providing safety through compile-time validation. This makes it uniquely suitable for writing low-level networking applications. 8 | 9 | This book is divided into three main parts that will take you on an exciting journey: building a fully functional web server. The book starts with a solid introduction to Rust and essential networking concepts. This will lay a foundation for, and set the tone of, the entire book. It takes an in-depth look at using Rust for networking software. Starting with client-server networking using sockets to IPv4/v6, DNS, TCP, UDP, you will also learn about serializing and deserializing data using serde. The book shows how to communicate with REST servers over HTTP and implement asynchronous network programming using the Tokio stack. Given the importance of security for modern systems, you will see how Rust supports common primitives such as TLS and public key cryptography. 10 | 11 | After reading this book, you will be more than confident enough to use Rust to build effective networking software. 12 | 13 | ## Instructions and Navigation 14 | All of the code is organized into folders. Each folder starts with a number followed by the application name. For example, Chapter02. 15 | 16 | There is no code in Chapter 1 17 | 18 | The code will look like the following: 19 | ``` 20 | [package] 21 | name = "hello-rust" 22 | version = "0.1.0" 23 | authors = ["Foo Bar "] 24 | ``` 25 | 26 | They are either already familiar with Rust or are planning to start learning the language 27 | They have a commercial background in software engineering using other programming languages and are aware about the tradeoffs in developing software using different programming languages 28 | They have a basic familiarity with networking concepts 29 | They can appreciate why distributed systems are important in modern computing 30 | 31 | ## Related Products 32 | * [Rust Blueprints](https://www.packtpub.com/application-development/rust-blueprints?utm_source=github&utm_medium=repository&utm_campaign=9781788473835) 33 | 34 | * [Rust High Performance](https://www.packtpub.com/application-development/rust-high-performance?utm_source=github&utm_medium=repository&utm_campaign=9781788399487) 35 | 36 | * [RUST Design Patterns and Best Practices](https://www.packtpub.com/application-development/rust-design-patterns-and-best-practices?utm_source=github&utm_medium=repository&utm_campaign=9781788833370) 37 | 38 | ### Suggestions and Feedback 39 | [Click here](https://docs.google.com/forms/d/e/1FAIpQLSe5qwunkGf6PUvzPirPDtuy1Du5Rlzew23UBp2S-P3wB-GcwQ/viewform) if you have any feedback or suggestions. 40 | ### Download a free PDF 41 | 42 | If you have already purchased a print or Kindle version of this book, you can get a DRM-free PDF version at no cost.
Simply click on the link to download a free PDF copy of this book.
43 |

https://packt.link/free-ebook/9781788624893

--------------------------------------------------------------------------------