Анонимни функции II

26 ноември 2019

Преговор

Fn traits

Преговор

move премества стойността, независимо как се използва

1 2 3 4 5 6 7 8
let nums = vec![0, 1, 2, 3];

// прихваща `nums` като `Vec<i32>`
let f = move || {
    for n in &nums {
        println!("{}", n);
    }
};
fn main() {
let nums = vec![0, 1, 2, 3];

// прихваща `nums` като `Vec`
let f = move || {
    for n in &nums {
        println!("{}", n);
    }
};
}

Moving closure captures

Няколко трика ако искаме да преместим някоя стойност, но да прихванем друга по референция

1 2 3 4 5 6 7 8 9 10 11 12
let nums = vec![0, 1, 2, 3];
let s = String::from("cookies");

let f = || {
    let nums = nums;         // move `nums`

    println!("{:?}", nums);
    println!("{:?}", s);
};

// println!("{:?}", nums);   // комп. грешка
println!("{:?}", s);
"cookies"
fn main() {
let nums = vec![0, 1, 2, 3];
let s = String::from("cookies");

let f = || {
    let nums = nums;         // move `nums`

    println!("{:?}", nums);
    println!("{:?}", s);
};

// println!("{:?}", nums);   // комп. грешка
println!("{:?}", s);
}

Moving closure captures

1 2 3 4 5 6 7 8 9 10 11
let nums = vec![0, 1, 2, 3];
let s = String::from("cookies");
let r = &s;             // move `r: &String`

let f = move || {
    println!("{:?}", nums);
    println!("{:?}", r);
};

// println!("{:?}", nums);   // комп. грешка
println!("{:?}", s);
"cookies"
fn main() {
let nums = vec![0, 1, 2, 3];
let s = String::from("cookies");
let r = &s;             // move `r: &String`

let f = move || {
    println!("{:?}", nums);
    println!("{:?}", r);
};

// println!("{:?}", nums);   // комп. грешка
println!("{:?}", s);
}

Saving closures

Да си направим адаптер за итератор, който работи подобно на
адаптера връщан от Iterator::map()

1 2 3 4 5 6 7
struct Map<I, F, B> where
    I: Iterator,
    F: FnMut(I::Item) -> B
{
    iter: I,
    f: F,
}
fn main() {}
struct Map where
    I: Iterator,
    F: FnMut(I::Item) -> B
{
    iter: I,
    f: F,
}

Saving closures

Имплементираме Iterator

1 2 3 4 5 6 7 8 9 10 11 12 13
impl<I, F, B> Iterator for Map<I, F, B> where
    I: Iterator,
    F: FnMut(I::Item) -> B
{
    type Item = B;

    fn next(&mut self) -> Option<Self::Item> {
        match self.iter.next() {
            Some(item) => Some((self.f)(item)),
            None => None,
        }
    }
}
struct Map where I: Iterator, F: FnMut(I::Item) -> B {
iter: I,
f: F,
}
fn main() {}
impl Iterator for Map where
    I: Iterator,
    F: FnMut(I::Item) -> B
{
    type Item = B;

    fn next(&mut self) -> Option {
        match self.iter.next() {
            Some(item) => Some((self.f)(item)),
            None => None,
        }
    }
}

Saving closures

Имплементираме Iterator

1 2 3 4 5 6 7 8 9 10 11 12 13
impl<I, F, B> Iterator for Map<I, F, B> where
    I: Iterator,
    F: FnMut(I::Item) -> B
{
    type Item = B;

    fn next(&mut self) -> Option<Self::Item> {
        match self.iter.next() {
            Some(item) => Some((self.f)(item)),
            None => None,
        }
    }
}
struct Map where I: Iterator, F: FnMut(I::Item) -> B {
iter: I,
f: F,
}
fn main() {}
impl Iterator for Map where
    I: Iterator,
    F: FnMut(I::Item) -> B
{
    type Item = B;

    fn next(&mut self) -> Option {
        match self.iter.next() {
            Some(item) => Some((self.f)(item)),
            None => None,
        }
    }
}

Забележете скобите около self.f

Saving closures

Малко улеснение

1 2 3 4 5 6 7 8 9 10
impl<I, F, B> Iterator for Map<I, F, B> where
    I: Iterator,
    F: FnMut(I::Item) -> B
{
    type Item = B;

    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|x| (self.f)(x))
    }
}
struct Map where I: Iterator, F: FnMut(I::Item) -> B {
iter: I,
f: F,
}
fn main() {}
impl Iterator for Map where
    I: Iterator,
    F: FnMut(I::Item) -> B
{
    type Item = B;

    fn next(&mut self) -> Option {
        self.iter.next().map(|x| (self.f)(x))
    }
}

Saving closures

1 2 3 4 5 6 7 8 9
// vec![1, 2, 3].into_iter().map(|x| x * 3)

let map = Map {
    iter: vec![1, 2, 3].into_iter(),
    f: |x| x * 3,
};

let v = map.collect::<Vec<_>>();
println!("{:?}", v);
[3, 6, 9]
struct Map where I: Iterator, F: FnMut(I::Item) -> B {
iter: I,
f: F,
}
impl Iterator for Map where
I: Iterator,
F: FnMut(I::Item) -> B
{
type Item = B;
fn next(&mut self) -> Option {
self.iter.next().map(|x| (self.f)(x))
}
}
fn main() {
// vec![1, 2, 3].into_iter().map(|x| x * 3)

let map = Map {
    iter: vec![1, 2, 3].into_iter(),
    f: |x| x * 3,
};

let v = map.collect::>();
println!("{:?}", v);
}

Returning closures

1 2 3
fn get_incrementer() -> ??? {
    |x| x + 1
}

Returning closures

Да проверим какъв е типът на closure-а

1
let _: () = |x| x + 1;

Returning closures

Да проверим какъв е типът на closure-а

1
let _: () = |x| x + 1;
error[E0308]: mismatched types --> src/bin/main_f4ff4185076e43830fdfe11463e56a301ab6f9e8.rs:2:13 | 2 | let _: () = |x| x + 1; | ^^^^^^^^^ expected (), found closure | = note: expected type `()` found type `[closure@src/bin/main_f4ff4185076e43830fdfe11463e56a301ab6f9e8.rs:2:13: 2:22]`
fn main() {
let _: () = |x| x + 1;
}

Тип генериран от компилатора, това не ни е полезно

Returning closures

Вариант 1

Ако closure не прихваща променливи, той може автоматично да се сведе до указател към функция

1 2 3
fn get_incrementer() -> fn(i32) -> i32 {
    |x| x + 1
}
fn main() {}
fn get_incrementer() -> fn(i32) -> i32 {
    |x| x + 1
}

Returning closures

Вариант 2

Често се налага да прихванем променливи

1 2 3
fn curry(a: u32) -> ??? {
    |b| a + b
}

Returning closures

Вариант 2

Можем да използваме Trait objects

1 2 3
struct F<'a> {
    closure: &'a dyn Fn()
}

Copy

fn main() {}
struct F<'a> {
    closure: &'a dyn Fn()
}

1 2 3
struct F {
    closure: Box<dyn Fn()>
}

Copy

fn main() {}
struct F {
    closure: Box
}

Returning closures

Вариант 2

Така дали ще е добре?

1 2 3
fn curry(a: u32) -> Box<dyn Fn(u32) -> u32> {
    Box::new(|b| a + b)
}

Returning closures

Вариант 2

Така дали ще е добре?

1 2 3
fn curry(a: u32) -> Box<dyn Fn(u32) -> u32> {
    Box::new(|b| a + b)
}
error[E0373]: closure may outlive the current function, but it borrows `a`, which is owned by the current function --> src/bin/main_c3074d2dcf287ba7bd8e52e50983e379c8e9c09b.rs:4:14 | 4 | Box::new(|b| a + b) | ^^^ - `a` is borrowed here | | | may outlive borrowed value `a` | note: closure is returned here --> src/bin/main_c3074d2dcf287ba7bd8e52e50983e379c8e9c09b.rs:4:5 | 4 | Box::new(|b| a + b) | ^^^^^^^^^^^^^^^^^^^ help: to force the closure to take ownership of `a` (and any other referenced variables), use the `move` keyword | 4 | Box::new(move |b| a + b) | ^^^^^^^^
fn main() {}
fn curry(a: u32) -> Box u32> {
    Box::new(|b| a + b)
}

Returning closures

Вариант 2

move

1 2 3 4 5
fn curry(a: u32) -> Box<dyn Fn(u32) -> u32> {
    Box::new(move |b| a + b)
}

println!("{}", curry(1)(2));
3
fn curry(a: u32) -> Box u32> {
    Box::new(move |b| a + b)
}

fn main() {
println!("{}", curry(1)(2));
}

Closures & lifetimes

А какво става, ако искаме да прихванем референция?

1 2 3
fn curry<'a>(a: &'a u32) -> Box<dyn Fn(&u32) -> u32> {
    Box::new(move |b| a + b)
}
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements --> src/bin/main_1fc5deed1c334e9a9574d1cbc23849d5468c176e.rs:3:14 | 3 | Box::new(move |b| a + b) | ^^^^^^^^^^^^^^ | note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 2:10... --> src/bin/main_1fc5deed1c334e9a9574d1cbc23849d5468c176e.rs:2:10 | 2 | fn curry<'a>(a: &'a u32) -> Box<dyn Fn(&u32) -> u32> { | ^^ = note: ...so that the types are compatible: expected &u32 found &'a u32 = note: but, the lifetime must be valid for the static lifetime... = note: ...so that the expression is assignable: expected std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r u32) -> u32 + 'static)> found std::boxed::Box<dyn for<'r> std::ops::Fn(&'r u32) -> u32>
fn main() {}
fn curry<'a>(a: &'a u32) -> Box u32> {
    Box::new(move |b| a + b)
}

Closures & lifetimes

1 2 3 4 5 6 7 8 9 10
struct State<'b> {
    a: &'b u32
}

// impl Fn, FnMut, FnOnce for State

fn curry<'a>(a: &'a u32) -> Box<State<'a>> {
    let state = State { a };    // State<'a>
    Box::new(state)             // очаква 'static
}

Closures & lifetimes

Lifetime на структура

Какво означава обект (който не е референция) да има 'static lifetime?

Lifetime-а показва максимално ограничение до което може да живее някаква стойност

1 2 3 4 5 6 7 8
struct Foo<'a> { a: &'a i32 }

{
    let a = 10;                     // ---+- 'a
                                    //    |
    let foo = Foo { a: &a };        // ---+- foo: 'a
                                    //    |
}                                   // <--+
fn main() {
struct Foo<'a> { a: &'a i32 }

{
    let a = 10;                     // ---+- 'a
                                    //    |
    let foo = Foo { a: &a };        // ---+- foo: 'a
                                    //    |
}                                   // <--+
}

Closures & lifetimes

Lifetime на структура

Когато обект не държи референции няма такова ограничение

Затова се приема че обекта има 'static lifetime

1 2 3 4 5 6 7
struct Foo { a: i32 }

{
    let a = 10;

    let foo = Foo { a: a };         // foo: 'static
}
fn main() {
struct Foo { a: i32 }

{
    let a = 10;

    let foo = Foo { a: a };         // foo: 'static
}
}

Closures & lifetimes

По подразбиране се очаква trait object-а да няма lifetime ограничение, т.е да е 'static

Box<dyn Fn(&u32) -> u32> <-> Box<dyn Fn(&u32) -> u32 + 'static>;

Ако имаме ограничение трябва да го укажем изрично

1 2 3 4 5
fn curry<'a>(a: &'a u32) -> Box<dyn Fn(&u32) -> u32 + 'a> {
    Box::new(move |b| a + b)
}

println!("{}", curry(&1)(&2));
3
fn curry<'a>(a: &'a u32) -> Box u32 + 'a> {
    Box::new(move |b| a + b)
}

fn main() {
println!("{}", curry(&1)(&2));
}

Returning closures

Вариант 3 (impl Trait)

1 2 3 4 5
fn curry(a: u32) -> impl Fn(u32) -> u32 {
    move |b| a + b
}

println!("{}", curry(1)(2));
3
fn curry(a: u32) -> impl Fn(u32) -> u32 {
    move |b| a + b
}

fn main() {
println!("{}", curry(1)(2));
}

impl Trait

Може да стои на мястото на типа на аргумент или return типа

1 2 3 4 5 6 7
use std::fmt::Debug;

fn id(arg: impl Debug) -> impl Debug {
    arg
}
println!("{:?}", id(1));
println!("{:?}", id("foo"));
1 "foo"
use std::fmt::Debug;

fn id(arg: impl Debug) -> impl Debug {
    arg
}
fn main() {
println!("{:?}", id(1));
println!("{:?}", id("foo"));
}

impl Trait

Не може да правите нищо друго с него освен това което имплементира

1 2 3 4 5 6
use std::fmt::Debug;

fn id(arg: impl Debug) -> impl Debug {
    arg
}
println!("{}", id(1));
error[E0277]: `impl std::fmt::Debug` doesn't implement `std::fmt::Display` --> src/bin/main_8bf7039ea5b999af5f79cbab4e653a034da9476d.rs:7:16 | 7 | println!("{}", id(1)); | ^^^^^ `impl std::fmt::Debug` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `impl std::fmt::Debug` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = note: required by `std::fmt::Display::fmt`
use std::fmt::Debug;

fn id(arg: impl Debug) -> impl Debug {
    arg
}
fn main() {
println!("{}", id(1));
}

impl Trait

Разликата между generics и impl Trait

EventEmitter

layout

Нека опитаме да напишем прост event emitter със следните изисквания:

EventEmitter

layout

Нека опитаме да напишем прост event emitter със следните изисквания:

EventEmitter

layout

Нека опитаме да напишем прост event emitter със следните изисквания:

EventEmitter

layout

Нека опитаме да напишем прост event emitter със следните изисквания:

EventEmitter

layout

Нека опитаме да напишем прост event emitter със следните изисквания:

EventEmitter

Пълният код може да се разгледа в Github - https://github.com/d3lio/simple-event-emitter

EventEmitter

usage

1 2 3 4 5 6 7 8
let mut emitter = EventEmitter::new();

let _  = emitter.on("woot", |p: String| println!("{}", p));
let id = emitter.on("woot", |_| println!("hi"));

emitter.off(id);

emitter.emit("woot", "boot".to_string());

EventEmitter

structures

Ето как би изглеждала структурата

1 2 3
struct EventEmitter<E, P> {
    map: HashMap<E, Vec<Box<dyn Fn(P)>>>
}
fn main() {}
use std::collections::HashMap;
struct EventEmitter {
    map: HashMap>>
}

EventEmitter

structures

Но, ще ни трябват някои допълнителни ограничения

1 2 3 4 5 6 7 8 9 10 11
type Id = u64;

struct Listener<P> {
    id: Id,
    closure: Box<dyn Fn(P)>
}

struct EventEmitter<E, P> where E: Eq + Hash, P: Clone {
    next_id: Id,
    map: HashMap<E, Vec<Listener<P>>>
}
fn main() {}
use std::collections::HashMap;
use std::hash::Hash;
type Id = u64;

struct Listener

{ id: Id, closure: Box } struct EventEmitter where E: Eq + Hash, P: Clone { next_id: Id, map: HashMap>> }

EventEmitter

constructors

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
impl<P> Listener<P> {
    fn new<F>(id: Id, f: F) -> Self where F: Fn(P) + 'static {
        Self {
            id,
            closure: Box::new(f)
        }
    }
}

impl<E, P> EventEmitter<E, P> where E: Eq + Hash, P: Clone {
    fn new() -> Self {
        Self {
            next_id: Id::default(),
            map: HashMap::new()
        }
    }
}
use std::collections::HashMap;
use std::hash::Hash;
fn main() {}
type Id = u64;
struct Listener

{ id: Id, closure: Box } struct EventEmitter where E: Eq + Hash, P: Clone { next_id: Id, map: HashMap>> } impl

Listener

{ fn new(id: Id, f: F) -> Self where F: Fn(P) + 'static { Self { id, closure: Box::new(f) } } } impl EventEmitter where E: Eq + Hash, P: Clone { fn new() -> Self { Self { next_id: Id::default(), map: HashMap::new() } } }

EventEmitter

on

Място, където map::Entry ще ни улесни

1 2 3 4 5 6 7 8 9 10 11
impl<E, P> EventEmitter<E, P> where E: Eq + Hash, P: Clone {
    fn on<F>(&mut self, event: E, listener: F) -> Id where F: Fn(P) + 'static {
        let id = self.next_id;
        let listeners = self.map.entry(event).or_insert(Vec::new());

        listeners.push(Listener::new(self.next_id, listener));

        self.next_id += 1;
        id
    }
}
use std::collections::HashMap;
use std::hash::Hash;
fn main() {}
type Id = u64;
struct Listener

{ id: Id, closure: Box } struct EventEmitter where E: Eq + Hash, P: Clone { next_id: Id, map: HashMap>> } impl

Listener

{ fn new(id: Id, f: F) -> Self where F: Fn(P) + 'static { Self { id, closure: Box::new(f) } } } impl EventEmitter where E: Eq + Hash, P: Clone { fn on(&mut self, event: E, listener: F) -> Id where F: Fn(P) + 'static { let id = self.next_id; let listeners = self.map.entry(event).or_insert(Vec::new()); listeners.push(Listener::new(self.next_id, listener)); self.next_id += 1; id } }

EventEmitter

off

1 2 3 4 5 6 7 8 9 10 11 12 13 14
impl<E, P> EventEmitter<E, P> where E: Eq + Hash, P: Clone {
    fn off(&mut self, id: Id) -> bool {
        for (_, listeners) in self.map.iter_mut() {
            let position = listeners.iter().position(|x| x.id == id);

            if let Some(idx) = position {
                listeners.remove(idx);
                return true;
            }
        }

        false
    }
}
fn main() {}
use std::collections::HashMap;
use std::hash::Hash;
type Id = u64;
struct Listener

{ id: Id, closure: Box } struct EventEmitter where E: Eq + Hash, P: Clone { next_id: Id, map: HashMap>> } impl EventEmitter where E: Eq + Hash, P: Clone { fn off(&mut self, id: Id) -> bool { for (_, listeners) in self.map.iter_mut() { let position = listeners.iter().position(|x| x.id == id); if let Some(idx) = position { listeners.remove(idx); return true; } } false } }

EventEmitter

emit

Ето една възможност да използваме Borrow

1 2 3 4 5 6 7 8 9 10 11 12 13
impl<E, P> EventEmitter<E, P> where E: Eq + Hash, P: Clone {
    fn emit<T>(&self, event: &T, payload: P) -> bool
    where E: Borrow<T>, T: ?Sized + Hash + Eq {
        match self.map.get(event) {
            Some(listeners) => {
                // Клонираме данните, за да може да ги подадем на всички слушатели
                listeners.iter().for_each(|f| (f.closure)(payload.clone()));
                true
            },
            None => false
        }
    }
}
fn main() {}
use std::collections::HashMap;
use std::hash::Hash;
use std::borrow::Borrow;
type Id = u64;
struct Listener

{ id: Id, closure: Box } struct EventEmitter where E: Eq + Hash, P: Clone { next_id: Id, map: HashMap>> } impl EventEmitter where E: Eq + Hash, P: Clone { fn emit(&self, event: &T, payload: P) -> bool where E: Borrow, T: ?Sized + Hash + Eq { match self.map.get(event) { Some(listeners) => { // Клонираме данните, за да може да ги подадем на всички слушатели listeners.iter().for_each(|f| (f.closure)(payload.clone())); true }, None => false } } }

Borrow

Какво точно прави този типаж?

Borrow

1 2 3
pub trait Borrow<Borrowed> where Borrowed: ?Sized {
    fn borrow(&self) -> &Borrowed;
}
fn main() {}
pub trait Borrow where Borrowed: ?Sized {
    fn borrow(&self) -> &Borrowed;
}

Borrow

Позволява ни да абстрахираме даден тип и да кажем, че искаме да получаваме всеки тип, който се конвертира до желания тип. В случая на този пример искаме да приемаме всичко, което може да се заеме като &str.

1 2 3 4 5 6 7 8 9 10 11 12 13 14
use std::borrow::Borrow;

fn check<T: Borrow<str>>(s: T) {
    println!("{}", s.borrow());
}

// В стандартната библиотека има impl Borrow<str> for String
let s = "Hello".to_string();

check(s);

let s = "Hello";

check(s);
Hello Hello
use std::borrow::Borrow;

fn check>(s: T) {
    println!("{}", s.borrow());
}

fn main() {
// В стандартната библиотека има impl Borrow for String
let s = "Hello".to_string();

check(s);

let s = "Hello";

check(s);
}

EventEmitter

1 2 3 4 5 6 7 8
let mut emitter = EventEmitter::new();

let _  = emitter.on("woot", |p: String| println!("{}", p));
let id = emitter.on("woot", |_| println!("hi"));

emitter.off(id);

emitter.emit("woot", "boot".to_string());
boot
use std::borrow::Borrow;
use std::collections::HashMap;
use std::hash::Hash;

type Id = u64;

pub struct Listener

{ id: Id, closure: Box } impl

Listener

{ pub fn new(id: Id, f: F) -> Self where F: Fn(P) + 'static { Self { id, closure: Box::new(f) } } } pub struct EventEmitter where E: Eq + Hash, P: Clone { next_id: Id, map: HashMap>> } impl EventEmitter where E: Eq + Hash, P: Clone { pub fn new() -> Self { Self { next_id: Id::default(), map: HashMap::new() } } pub fn on(&mut self, event: E, listener: F) -> Id where F: Fn(P) + 'static { let id = self.next_id; let listeners = self.map.entry(event).or_insert(Vec::new()); listeners.push(Listener::new(self.next_id, listener)); self.next_id += 1; id } pub fn off(&mut self, id: Id) -> bool { for (_, listeners) in self.map.iter_mut() { let position = listeners.iter().position(|x| x.id == id); if let Some(idx) = position { listeners.remove(idx); return true; } } false } pub fn emit(&self, event: &T, payload: P) -> bool where E: Borrow, T: ?Sized + Hash + Eq { match self.map.get(event) { Some(listeners) => { listeners.iter().for_each(|f| (f.closure)(payload.clone())); true }, None => false } } } fn main() { let mut emitter = EventEmitter::new(); let _ = emitter.on("woot", |p: String| println!("{}", p)); let id = emitter.on("woot", |_| println!("hi")); emitter.off(id); emitter.emit("woot", "boot".to_string()); }

Networking

Стандартната библиотека имплементира networking примитиви в модула std::net

UDP

UdpSocket

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
use std::net::UdpSocket;

// сокета се затваря на края на scope-a
fn main() {
    let mut socket = UdpSocket::bind("127.0.0.1:34254").unwrap();

    // Получава една дейтаграма от сокета. Ако буфера е прекалено малък за съобщението,
    // то ще бъде орязано.
    let mut buf = [0; 10];
    let (amt, src) = socket.recv_from(&mut buf).unwrap();

    // Редекларира `buf` като слайс от получените данни и ги праща в обратен ред.
    let buf = &mut buf[..amt];
    buf.reverse();
    socket.send_to(buf, &src).unwrap();
}
use std::net::UdpSocket;

// сокета се затваря на края на scope-a
fn main() {
    let mut socket = UdpSocket::bind("127.0.0.1:34254").unwrap();

    // Получава една дейтаграма от сокета. Ако буфера е прекалено малък за съобщението,
    // то ще бъде орязано.
    let mut buf = [0; 10];
    let (amt, src) = socket.recv_from(&mut buf).unwrap();

    // Редекларира `buf` като слайс от получените данни и ги праща в обратен ред.
    let buf = &mut buf[..amt];
    buf.reverse();
    socket.send_to(buf, &src).unwrap();
}

TCP

TcpStream

1 2 3 4 5 6 7 8 9 10
use std::io::prelude::*;
use std::net::TcpStream;

// стриймът се затваря на края на scope-a
fn main() {
    let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap();

    let _ = stream.write(&[1]);
    let _ = stream.read(&mut [0; 128]);
}
use std::io::prelude::*;
use std::net::TcpStream;

// стриймът се затваря на края на scope-a
fn main() {
    let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap();

    let _ = stream.write(&[1]);
    let _ = stream.read(&mut [0; 128]);
}

TCP

TcpListener

1 2 3 4 5 6 7 8 9 10 11 12 13 14
use std::net::{TcpListener, TcpStream};

fn handle_client(stream: TcpStream) {
    // ...
}

fn main() {
    let listener = TcpListener::bind("127.0.0.1:80").unwrap();

    // приема конекции и ги обработва
    for stream in listener.incoming() {
        handle_client(stream.unwrap());
    }
}
use std::net::{TcpListener, TcpStream};

fn handle_client(stream: TcpStream) {
    // ...
}

fn main() {
    let listener = TcpListener::bind("127.0.0.1:80").unwrap();

    // приема конекции и ги обработва
    for stream in listener.incoming() {
        handle_client(stream.unwrap());
    }
}

TCP

Simple chat

Ще разгледаме проста чат система за демонстрация на нишки, канали и TCP

Пълният код може да се разгледа в Github - https://github.com/d3lio/simple-chat

TCP

Simple chat

Какво няма да обхванем:

TCP

Simple chat

Какво няма да обхванем:

TCP

Simple chat

Какво няма да обхванем:

Simple chat

Server

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
use std::net::{TcpListener, TcpStream};
use std::sync::mpsc;
use std::thread;
use std::time::Duration;

const LOCALHOST: &str = "127.0.0.1:1234";
const MESSAGE_SIZE: usize = 32;

fn main() {
    let server = TcpListener::bind(LOCALHOST).expect("Listener failed to bind");
    server.set_nonblocking(true).expect("Failed to initialize nonblocking");

    // Stores client sockets
    let mut clients = Vec::<TcpStream>::new();
    let (sx, rx) = mpsc::channel::<String>();

    loop {
        /* accept */
        /* broadcast */
        thread::sleep(Duration::from_millis(100));
    }
}
use std::net::{TcpListener, TcpStream};
use std::sync::mpsc;
use std::thread;
use std::time::Duration;

const LOCALHOST: &str = "127.0.0.1:1234";
const MESSAGE_SIZE: usize = 32;

fn main() {
    let server = TcpListener::bind(LOCALHOST).expect("Listener failed to bind");
    server.set_nonblocking(true).expect("Failed to initialize nonblocking");

    // Stores client sockets
    let mut clients = Vec::::new();
    let (sx, rx) = mpsc::channel::();

    loop {
        /* accept */
        /* broadcast */
        thread::sleep(Duration::from_millis(100));
    }
}

Server

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
use std::io::{ErrorKind, Read, Write};
use std::net::TcpListener;
use std::sync::mpsc;
use std::thread;
use std::time::Duration;

fn sleep() {
    thread::sleep(Duration::from_millis(100));
}

const LOCALHOST: &str = "127.0.0.1:1234";
const MESSAGE_SIZE: usize = 32;

fn main() {
    let server = TcpListener::bind(LOCALHOST).expect("Listener failed to bind");
    server.set_nonblocking(true).expect("Failed to initialize nonblocking");

    let mut clients = Vec::new();
    let (sx, rx) = mpsc::channel::<String>();

    loop {
        // Try to accept a client
        if let Ok((mut socket, addr)) = server.accept() {
            println!("Client {} connected", addr);

            let sx = sx.clone();

            clients.push(socket.try_clone().expect("Failed to clone client"));

            thread::spawn(move || loop {
                let mut buf = vec![0; MESSAGE_SIZE];

                // Try to receive message from client
                match socket.read_exact(&mut buf) {
                    Ok(_) => {
                        let msg = buf.into_iter().take_while(|&x| x != 0).collect::<Vec<_>>();
                        let msg = String::from_utf8(msg).expect("Invalid utf8 message");

                        println!("{}: {:?}", addr, msg);
                        sx.send(msg).expect("Send to master channel failed");
                    },
                    Err(ref err) if err.kind() == ErrorKind::WouldBlock => (),
                    Err(_) => {
                        println!("Closing connection with: {}", addr);
                        break;
                    }
                }

                sleep();
            });
        }

        if let Ok(msg) = rx.try_recv() {
            // Try to send message from master channel
            clients = clients.into_iter().filter_map(|mut client| {
                let mut buf = msg.clone().into_bytes();
                buf.resize(MESSAGE_SIZE, 0);

                match client.write_all(&buf) {
                    Ok(_) => Some(client),
                    _ => None,
                }
            }).collect::<Vec<_>>();
        }

        sleep();
    }
}
use std::io::{ErrorKind, Read, Write};
use std::net::TcpListener;
use std::sync::mpsc;
use std::thread;
use std::time::Duration;

fn sleep() {
    thread::sleep(Duration::from_millis(100));
}

const LOCALHOST: &str = "127.0.0.1:1234";
const MESSAGE_SIZE: usize = 32;

fn main() {
    let server = TcpListener::bind(LOCALHOST).expect("Listener failed to bind");
    server.set_nonblocking(true).expect("Failed to initialize nonblocking");

    let mut clients = Vec::new();
    let (sx, rx) = mpsc::channel::();

    loop {
        // Try to accept a client
        if let Ok((mut socket, addr)) = server.accept() {
            println!("Client {} connected", addr);

            let sx = sx.clone();

            clients.push(socket.try_clone().expect("Failed to clone client"));

            thread::spawn(move || loop {
                let mut buf = vec![0; MESSAGE_SIZE];

                // Try to receive message from client
                match socket.read_exact(&mut buf) {
                    Ok(_) => {
                        let msg = buf.into_iter().take_while(|&x| x != 0).collect::>();
                        let msg = String::from_utf8(msg).expect("Invalid utf8 message");

                        println!("{}: {:?}", addr, msg);
                        sx.send(msg).expect("Send to master channel failed");
                    },
                    Err(ref err) if err.kind() == ErrorKind::WouldBlock => (),
                    Err(_) => {
                        println!("Closing connection with: {}", addr);
                        break;
                    }
                }

                sleep();
            });
        }

        if let Ok(msg) = rx.try_recv() {
            // Try to send message from master channel
            clients = clients.into_iter().filter_map(|mut client| {
                let mut buf = msg.clone().into_bytes();
                buf.resize(MESSAGE_SIZE, 0);

                match client.write_all(&buf) {
                    Ok(_) => Some(client),
                    _ => None,
                }
            }).collect::>();
        }

        sleep();
    }
}

Simple chat

Client

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
use std::net::TcpStream;
use std::sync::mpsc;
use std::thread;
use std::time::Duration;

const LOCALHOST: &str = "127.0.0.1:1234";
const MESSAGE_SIZE: usize = 32;

fn main() {
    let mut client = TcpStream::connect(LOCALHOST).expect("Stream failed to connect");
    client.set_nonblocking(true).expect("Failed to initialize nonblocking");

    let (sx, rx) = mpsc::channel::<String>();

    thread::spawn(move || loop {
        /* try recv */
        /* try send */
        thread::sleep(Duration::from_millis(100));
    });

    /* repl */
}
use std::net::TcpStream;
use std::sync::mpsc;
use std::thread;
use std::time::Duration;

const LOCALHOST: &str = "127.0.0.1:1234";
const MESSAGE_SIZE: usize = 32;

fn main() {
    let mut client = TcpStream::connect(LOCALHOST).expect("Stream failed to connect");
    client.set_nonblocking(true).expect("Failed to initialize nonblocking");

    let (sx, rx) = mpsc::channel::();

    thread::spawn(move || loop {
        /* try recv */
        /* try send */
        thread::sleep(Duration::from_millis(100));
    });

    /* repl */
}

Client

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
use std::io::{self, ErrorKind, Read, Write};
use std::net::TcpStream;
use std::sync::mpsc::{self, TryRecvError};
use std::thread;
use std::time::Duration;

const LOCALHOST: &str = "127.0.0.1:1234";
const MESSAGE_SIZE: usize = 32;

fn main() {
    let mut client = TcpStream::connect(LOCALHOST).expect("Stream failed to connect");
    client.set_nonblocking(true).expect("Failed to initialize nonblocking");

    let (sx, rx) = mpsc::channel::<String>();

    thread::spawn(move || loop {
        let mut buf = vec![0; MESSAGE_SIZE];

        // Try to receive message from server
        match client.read_exact(&mut buf) {
            Ok(_) => {
                let msg = buf.into_iter().take_while(|&x| x != 0).collect::<Vec<_>>();
                let msg = String::from_utf8(msg).expect("Invalid utf8 message");
                println!("message recv {:?}", msg);
            },
            Err(ref err) if err.kind() == ErrorKind::WouldBlock => (),
            Err(_) => {
                println!("Connection with the server closed");
                break;
            }
        }

        // Try to send message from repl
        match rx.try_recv() {
            Ok(msg) => {
                let mut buf = msg.clone().into_bytes();
                buf.resize(MESSAGE_SIZE, 0);
                client.write_all(&buf).expect("Writing to socket failed");
                println!("message sent {:?}", msg);
            },
            Err(TryRecvError::Empty) => (),
            Err(TryRecvError::Disconnected) => break
        }

        thread::sleep(Duration::from_millis(100));
    });

    println!("repl");
    loop {
        let mut buf = String::new();
        io::stdin().read_line(&mut buf).expect("Reading from stdin failed");
        let msg = buf.trim().to_string();

        if msg == ":q" || sx.send(msg).is_err() { break }
    }
    println!("bye!");
}
use std::io::{self, ErrorKind, Read, Write};
use std::net::TcpStream;
use std::sync::mpsc::{self, TryRecvError};
use std::thread;
use std::time::Duration;

const LOCALHOST: &str = "127.0.0.1:1234";
const MESSAGE_SIZE: usize = 32;

fn main() {
    let mut client = TcpStream::connect(LOCALHOST).expect("Stream failed to connect");
    client.set_nonblocking(true).expect("Failed to initialize nonblocking");

    let (sx, rx) = mpsc::channel::();

    thread::spawn(move || loop {
        let mut buf = vec![0; MESSAGE_SIZE];

        // Try to receive message from server
        match client.read_exact(&mut buf) {
            Ok(_) => {
                let msg = buf.into_iter().take_while(|&x| x != 0).collect::>();
                let msg = String::from_utf8(msg).expect("Invalid utf8 message");
                println!("message recv {:?}", msg);
            },
            Err(ref err) if err.kind() == ErrorKind::WouldBlock => (),
            Err(_) => {
                println!("Connection with the server closed");
                break;
            }
        }

        // Try to send message from repl
        match rx.try_recv() {
            Ok(msg) => {
                let mut buf = msg.clone().into_bytes();
                buf.resize(MESSAGE_SIZE, 0);
                client.write_all(&buf).expect("Writing to socket failed");
                println!("message sent {:?}", msg);
            },
            Err(TryRecvError::Empty) => (),
            Err(TryRecvError::Disconnected) => break
        }

        thread::sleep(Duration::from_millis(100));
    });

    println!("repl");
    loop {
        let mut buf = String::new();
        io::stdin().read_line(&mut buf).expect("Reading from stdin failed");
        let msg = buf.trim().to_string();

        if msg == ":q" || sx.send(msg).is_err() { break }
    }
    println!("bye!");
}

Въпроси