1use std::hash::{DefaultHasher, Hash, Hasher};
23use colored::{Color, Colorize};
4use hydro_lang::*;
5use palette::{FromColor, Hsv, Srgb};
67pub struct Server {}
89pub struct Clients {}
1011use serde::{Deserialize, Serialize};
1213#[derive(Serialize, Deserialize, Clone)]
14pub struct ChatMsg {
15pub content: String,
16}
1718// To enable colored output in the terminal, set the environment variable
19// `CLICOLOR_FORCE=1`. By default, the `colored` crate only applies color
20// when the output is a terminal, to avoid issues with terminals that do
21// not support color.
22pub fn chat_server<'a>(flow: &FlowBuilder<'a>) -> (Process<'a, Server>, Cluster<'a, Clients>) {
23// For testing, use a fixed cluster of clients. In future we should support unbounded clients.
24 // This is a workaround for the fact that we don't have a way to create a cluster of
25 // unbounded clients in the current version of hydro.
2627let clients = flow.cluster::<Clients>();
28// Assume single server.
29let server = flow.process::<Server>();
3031// 1 chat message is generated from each client
32let client_requests = clients
33 .source_iter(q!([ChatMsg {
34 content: format!("Hi, it's me! Client #{}!", CLUSTER_SELF_ID.raw_id)
35 }]))
36 .send_bincode(&server)
37 .clone()
38 .inspect(q!(|(id, msg)| println!(
39"...forwarding chat {} from client #{}...",
40 msg.content, id
41 )));
42 client_requests
43 .broadcast_bincode(&clients)
44 .map(q!(|(id, msg)| (
45 id,
46 msg.content.color(self::hash_to_color(id.raw_id + 10))
47 )))
48 .for_each(q!(|(id, m)| println!("From {}: {:}", id.raw_id, m)));
4950 (server, clients)
51}
5253fn hash_to_color<T: Hash>(input: T) -> Color {
54let mut hasher = DefaultHasher::new();
55 input.hash(&mut hasher);
56let hash = hasher.finish();
5758// Map hash to a hue between 0–360
59let hue = (hash % 360) as f32;
60let hsv = Hsv::new(hue, 1.0, 1.0);
61let rgb: Srgb<u8> = Srgb::from_color(hsv).into_format();
6263 Color::TrueColor {
64 r: rgb.red,
65 g: rgb.green,
66 b: rgb.blue,
67 }
68}