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

22 ноември 2018

Преговор

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);
    }
};

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"

Moving closure captures

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

{
    let s = &s;             // move `s: &String`

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

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

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,
}

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,
        }
    }
}

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))
    }
}

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]

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 --> /main_f4ff4185076e43830fdfe11463e56a301ab6f9e8.rs:2:13 | 2 | let _: () = |x| x + 1; | ^^^^^^^^^ expected (), found closure | = note: expected type `()` found type `[closure@/main_f4ff4185076e43830fdfe11463e56a301ab6f9e8.rs:2:13: 2:22]`

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

Returning closures

Вариант 1

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

1 2 3
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 Fn()
}

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

Returning closures

Вариант 2

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

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

Returning closures

Вариант 2

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

1 2 3
fn curry(a: u32) -> Box<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 --> /main_b925fec74e8963be19f9a39c9c688dab6f0b453d.rs:4:14 | 4 | Box::new(|b| a + b) | ^^^ - `a` is borrowed here | | | may outlive borrowed value `a` 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) | ^^^^^^^^

Returning closures

Вариант 2

move

1 2 3 4
fn curry(a: u32) -> Box<Fn(u32) -> u32> {
    Box::new(move |b| a + b)
}
assert_eq!(curry(1)(2), 3);

Closures & lifetimes

1 2 3
fn curry<'a>(a: &'a u32) -> Box<Fn(&u32) -> u32> {
    Box::new(move |b| a + b)
}
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements --> /main_698f4bc0a6590f9f7f37c0d31d5c3b0cabdf3a02.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... --> /main_698f4bc0a6590f9f7f37c0d31d5c3b0cabdf3a02.rs:2:10 | 2 | fn curry<'a>(a: &'a u32) -> Box<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>

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
                                    //    |
}                                   // <--+

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
}

Closures & lifetimes

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

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

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

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

Returning closures

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

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

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"

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` --> /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`

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

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<Fn(P)>>>
}

EventEmitter

structures

Изглежда лесно…

EventEmitter

structures

Но нещата не са толкова прости

1 2 3
struct EventEmitter<E, P> {
    map: HashMap<E, Vec<Box<Fn(P)>>>
}

EventEmitter

structures

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

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

struct EventEmitter<E, P> where E: Eq + Hash, P: Clone {
    next_id: Id,
    map: HashMap<E, Vec<Listener<P>>>
}

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()
        }
    }
}

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
    }
}

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
    }
}

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<B>(&self, event: &B, payload: P) -> bool
    where E: Borrow<B>, B: ?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;
}

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

Event emitter

До тук какво имаме

Event emitter

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
struct EventEmitter<E, P> where E: Eq + Hash, P: Clone {
    next_id: Id,
    map: HashMap<E, Vec<Listener<P>>>
}

impl<E, P> EventEmitter<E, P> where E: Eq + Hash, P: Clone {
    fn new() -> Self { ... }

    /// Регистрира слушател
    fn on<F>(&mut self, event: E, listener: F) -> Id
    where F: Fn(P) + 'static { ... }

    /// Премахва слушател
    fn off(&mut self, id: Id) -> bool { ... }

    /// Излъчва съобщение с данни
    fn emit<B>(&self, event: &B, payload: P) -> bool
    where E: Borrow<B>, B: ?Sized + Hash + Eq { ... }
}

Event emitter

Тази имплементация има един проблем - какво става, ако излъчваме големи данни? Ще ги копираме всеки път като ги подаваме на event handler. Тогава бихме искали да подадем данните чрез референция.

1 2 3 4 5
let mut emitter = EventEmitter::new();
emitter.on("woot", |p: &str| println!("{}", p));

let data = "boot".to_string();
emitter.emit("woot", &data);

Event emitter

1 2 3 4 5
let mut emitter = EventEmitter::new();
emitter.on("woot", |p: &str| println!("{}", p));

let data = "boot".to_string();
emitter.emit("woot", &data);
error[E0597]: `data` does not live long enough --> /main_83dcb7adc1aaaf166e148fc671bc33a6d5a074ef.rs:51:23 | 51 | emitter.emit("woot", &data); | ^^^^ borrowed value does not live long enough 52 | } | - `data` dropped here while still borrowed | = note: values in a scope are dropped in the opposite order they are created

Защо?

Event emitter

Още по-странно, ако преместим data над emitter, всичко работи

1 2 3 4 5 6
let data = "boot".to_string();

let mut emitter = EventEmitter::new();
emitter.on("woot", |p: &str| println!("{}", p));

emitter.emit("woot", &data);
boot

Event emitter

emitter няма lifetime, но иска да живее повече от data…

… а дали е така?

Event emitter

1 2 3 4 5
emitter.emit("boot", &data);

fn emit<B>(&self, event: B, payload: P) -> bool where B: Borrow<E> { ... }

// => P = &'a str

Event emitter

1 2 3 4 5
let mut emitter = EventEmitter::new();            // EventEmitter<E = ?, P = ?>
emitter.on("woot", |p: &str| println!("{}", p));  // EventEmitter<&'static str, &'??? str>

let data = "boot".to_string();
emitter.emit("woot", &data);                      // EventEmitter<&'static str, &'a str>

P ограничава колко може да живее emitter

Event emitter

Решението: P -> &P

1 2 3 4 5 6 7
fn emit<B>(&self, event: &B, payload: &P) -> bool
where E: Borrow<B>, B: ?Sized + Hash + Eq { ... }

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

Event emitter

1 2 3 4 5
let mut emitter = EventEmitter::new();
emitter.on("woot", |p: &str| println!("{}", p));

let data = "boot".to_string();
emitter.emit("woot", &data);
error[E0277]: the size for values of type `str` cannot be known at compilation time --> /main_b2a5b75b57157fab2a44e4d6568045f02c6b1272.rs:57:19 | 57 | let mut emitter = EventEmitter::new(); | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `str` = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait> note: required by `<EventEmitter<E, P>>::new` --> /main_b2a5b75b57157fab2a44e4d6568045f02c6b1272.rs:22:1 | 22 | fn new() -> Self { | ^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `str` cannot be known at compilation time --> /main_b2a5b75b57157fab2a44e4d6568045f02c6b1272.rs:58:9 | 58 | emitter.on("woot", |p: &str| println!("{}", p)); | ^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `str` = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait> error[E0599]: no method named `emit` found for type `EventEmitter<&str, str>` in the current scope --> /main_b2a5b75b57157fab2a44e4d6568045f02c6b1272.rs:61:9 | 9 | struct EventEmitter<E, P> where E: Eq + Hash { | -------------------------------------------- method `emit` not found for this ... 61 | emitter.emit("woot", &data); | ^^^^ | = note: the method `emit` exists but the following trait bounds were not satisfied: `str : std::marker::Sized`

Event emitter

Добре, тъй като си избрахме като тип &str имаме да решим допълнителен проблем.

P се опитва да бъде str, който не е Sized и на компилатора не му харесва,
защото по подразбиране всеки тип трябва да е Sized.

Event emitter

С подсказките от компилатора и това че използваме P само зад референция (&P) можем спокойно да добавим "ограничение" ?Sized

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
struct Listener<P> where P: ?Sized {
    // ...
}

impl<P> Listener<P> where P: ?Sized {
    // ...
}

struct EventEmitter<E, P> where E: Eq + Hash, P: ?Sized {
    // ...
}

impl<E, P> EventEmitter<E, P> where E: Eq + Hash, P: ?Sized {
    // ...
}

fn main() {
    let mut emitter = EventEmitter::new();
    emitter.on("woot", |p: &str| println!("{}", p));

    let data = "boot".to_string();
    emitter.emit("woot", &data);
}
boot

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();
}

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]);
}

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());
    }
}

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));
    }
}

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
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);

                client.write_all(&buf).map(|_| client).ok()
            }).collect::<Vec<_>>();
        }

        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 */
}

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 form stdin failed");
        let msg = buf.trim().to_string();

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

Въпроси