From ee2e621d5b19de08becd33c13520f8826407cf84 Mon Sep 17 00:00:00 2001 From: Eskil Queseth Date: Sat, 17 Oct 2020 15:00:27 +0200 Subject: change data in response to channel-list to a tree --- mumd/src/state.rs | 340 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 336 insertions(+), 4 deletions(-) (limited to 'mumd') diff --git a/mumd/src/state.rs b/mumd/src/state.rs index 82d671e..4f37364 100644 --- a/mumd/src/state.rs +++ b/mumd/src/state.rs @@ -6,10 +6,12 @@ use mumble_protocol::control::msgs; use mumble_protocol::control::ControlPacket; use mumble_protocol::voice::Serverbound; use mumlib::command::{Command, CommandResponse}; -use mumlib::state::Server; use std::net::ToSocketAddrs; use tokio::sync::{mpsc, watch}; use mumlib::error::Error; +use std::collections::hash_map::Entry; +use std::collections::HashMap; +use serde::{Serialize, Deserialize}; #[derive(Clone, Debug, Eq, PartialEq)] pub enum StatePhase { @@ -73,7 +75,9 @@ impl State { return (false, Err(Error::DisconnectedError)); } (false, Ok(Some(CommandResponse::ChannelList { - channels: self.server.as_ref().unwrap().channels().clone(), + channels: into_channel( + self.server.as_ref().unwrap().channels().clone(), + self.server.as_ref().unwrap().users().clone()), })), ) } @@ -115,10 +119,11 @@ impl State { } ( false, - Ok(Some(CommandResponse::Status { + /*Ok(Some(CommandResponse::Status { username: self.username.clone(), server_state: self.server.clone().unwrap(), //guaranteed not to panic because if we are connected, server is guaranteed to be Some - })), + })),*/ + Err(Error::DisconnectedError) ) } Command::ServerDisconnect => { @@ -195,3 +200,330 @@ impl State { self.username.as_ref() } } + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct Server { + channels: HashMap, + users: HashMap, + pub welcome_text: Option, +} + +impl Server { + pub fn new() -> Self { + Self { + channels: HashMap::new(), + users: HashMap::new(), + welcome_text: None, + } + } + + pub fn parse_server_sync(&mut self, mut msg: msgs::ServerSync) { + if msg.has_welcome_text() { + self.welcome_text = Some(msg.take_welcome_text()); + } + } + + pub fn parse_channel_state(&mut self, msg: msgs::ChannelState) { + if !msg.has_channel_id() { + warn!("Can't parse channel state without channel id"); + return; + } + match self.channels.entry(msg.get_channel_id()) { + Entry::Vacant(e) => { + e.insert(Channel::new(msg)); + } + Entry::Occupied(mut e) => e.get_mut().parse_channel_state(msg), + } + } + + pub fn parse_channel_remove(&mut self, msg: msgs::ChannelRemove) { + if !msg.has_channel_id() { + warn!("Can't parse channel remove without channel id"); + return; + } + match self.channels.entry(msg.get_channel_id()) { + Entry::Vacant(_) => { + warn!("Attempted to remove channel that doesn't exist"); + } + Entry::Occupied(e) => { + e.remove(); + } + } + } + + pub fn parse_user_state(&mut self, msg: msgs::UserState) { + if !msg.has_session() { + warn!("Can't parse user state without session"); + return; + } + match self.users.entry(msg.get_session()) { + Entry::Vacant(e) => { + e.insert(User::new(msg)); + } + Entry::Occupied(mut e) => e.get_mut().parse_user_state(msg), + } + } + + pub fn channels(&self) -> &HashMap { + &self.channels + } + + pub fn users(&self) -> &HashMap { + &self.users + } +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct Channel { + description: Option, + links: Vec, + max_users: u32, + name: String, + parent: Option, + position: i32, +} + +impl Channel { + pub fn new(mut msg: msgs::ChannelState) -> Self { + Self { + description: if msg.has_description() { + Some(msg.take_description()) + } else { + None + }, + links: Vec::new(), + max_users: msg.get_max_users(), + name: msg.take_name(), + parent: if msg.has_parent() { + Some(msg.get_parent()) + } else { + None + }, + position: msg.get_position(), + } + } + + pub fn parse_channel_state(&mut self, mut msg: msgs::ChannelState) { + if msg.has_description() { + self.description = Some(msg.take_description()); + } + self.links = msg.take_links(); + if msg.has_max_users() { + self.max_users = msg.get_max_users(); + } + if msg.has_name() { + self.name = msg.take_name(); + } + if msg.has_parent() { + self.parent = Some(msg.get_parent()); + } + if msg.has_position() { + self.position = msg.get_position(); + } + } + + pub fn name(&self) -> &str { + &self.name + } +} + +#[derive(Debug)] +struct ProtoTree<'a> { + channel: Option<&'a Channel>, + children: HashMap>, + users: Vec<&'a User> +} + +impl<'a> ProtoTree<'a> { + fn walk_and_add(&mut self, channel: &'a Channel, users: &HashMap>, walk: &[u32]) { + match walk { + [] => unreachable!("nu gick något snett"), + &[node] => { + let pt = self.children.entry(node).or_insert(ProtoTree { + channel: None, + children: HashMap::new(), + users: Vec::new() + }); + pt.channel = Some(channel); + pt.users = users.get(&node).map(|e| e.clone()).unwrap_or(Vec::new()); + } + longer => { + self.children.entry(longer[0]).or_insert(ProtoTree { + channel: None, + children: HashMap::new(), + users: Vec::new() + }).walk_and_add(channel, users, &walk[1..]); + } + } + } +} + +impl<'a> From<&ProtoTree<'a>> for mumlib::state::Channel { + fn from(tree: &ProtoTree<'a>) -> Self { + let mut c = mumlib::state::Channel::from(tree.channel.unwrap()); + let mut children = tree.children.iter() + .map(|e| (e.1.channel.unwrap().position, mumlib::state::Channel::from(e.1))) + .collect::>(); + children.sort_by_key(|e| e.0); + c.children = children.into_iter().map(|e| e.1).collect(); + c.users = tree.users.iter().map(|e| (*e).into()).collect(); + c + } +} + +pub fn into_channel(channels: HashMap, users: HashMap) -> mumlib::state::Channel { + let mut walks = Vec::new(); + + let mut channel_lookup = HashMap::new(); + + for (_, user) in &users { + channel_lookup.entry(user.channel).or_insert(Vec::new()).push(user); + } + + debug!("{:?}", channel_lookup); + + for (channel_id, channel) in &channels { + let mut walk = Vec::new(); + let mut current = *channel_id; + while let Some(next) = channels.get(¤t).unwrap().parent { + walk.push(current); + current = next; + } + walk.reverse(); + + if walk.len() > 0 { + walks.push((walk, channel)); + } + } + + let mut proto_tree = ProtoTree { + channel: Some(channels.get(&0).unwrap()), + children: HashMap::new(), + users: channel_lookup.get(&0).map(|e| e.clone()).unwrap_or(Vec::new()), + }; + + for (walk, channel) in walks { + proto_tree.walk_and_add(channel, &channel_lookup, &walk); + } + + debug!("{:#?}", channels); + debug!("{:#?}", proto_tree); + + (&proto_tree).into() +} + +impl From<&Channel> for mumlib::state::Channel { + fn from(channel: &Channel) -> Self { + mumlib::state::Channel { + description: channel.description.clone(), + links: Vec::new(), + max_users: channel.max_users, + name: channel.name.clone(), + children: Vec::new(), + users: Vec::new() + } + } +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct User { + channel: u32, + comment: Option, + hash: Option, + name: String, + priority_speaker: bool, + recording: bool, + + suppress: bool, // by me + self_mute: bool, // by self + self_deaf: bool, // by self + mute: bool, // by admin + deaf: bool, // by admin +} + +impl User { + pub fn new(mut msg: msgs::UserState) -> Self { + Self { + channel: msg.get_channel_id(), + comment: if msg.has_comment() { + Some(msg.take_comment()) + } else { + None + }, + hash: if msg.has_hash() { + Some(msg.take_hash()) + } else { + None + }, + name: msg.take_name(), + priority_speaker: msg.has_priority_speaker() && msg.get_priority_speaker(), + recording: msg.has_recording() && msg.get_recording(), + suppress: msg.has_suppress() && msg.get_suppress(), + self_mute: msg.has_self_mute() && msg.get_self_mute(), + self_deaf: msg.has_self_deaf() && msg.get_self_deaf(), + mute: msg.has_mute() && msg.get_mute(), + deaf: msg.has_deaf() && msg.get_deaf(), + } + } + + pub fn parse_user_state(&mut self, mut msg: msgs::UserState) { + if msg.has_channel_id() { + self.channel = msg.get_channel_id(); + } + if msg.has_comment() { + self.comment = Some(msg.take_comment()); + } + if msg.has_hash() { + self.hash = Some(msg.take_hash()); + } + if msg.has_name() { + self.name = msg.take_name(); + } + if msg.has_priority_speaker() { + self.priority_speaker = msg.get_priority_speaker(); + } + if msg.has_recording() { + self.recording = msg.get_recording(); + } + if msg.has_suppress() { + self.suppress = msg.get_suppress(); + } + if msg.has_self_mute() { + self.self_mute = msg.get_self_mute(); + } + if msg.has_self_deaf() { + self.self_deaf = msg.get_self_deaf(); + } + if msg.has_mute() { + self.mute = msg.get_mute(); + } + if msg.has_deaf() { + self.deaf = msg.get_deaf(); + } + } + + pub fn name(&self) -> &str { + &self.name + } + + pub fn channel(&self) -> u32 { + self.channel + } +} + +impl From<&User> for mumlib::state::User { + fn from(user: &User) -> Self { + mumlib::state::User { + comment: user.comment.clone(), + hash: user.hash.clone(), + name: user.name.clone(), + priority_speaker: user.priority_speaker, + recording: user.recording, + suppress: user.suppress, + self_mute: user.self_mute, + self_deaf: user.self_deaf, + mute: user.mute, + deaf: user.deaf, + } + } +} \ No newline at end of file -- cgit v1.2.1 From 8213d5769c771641f906611aeb427a93f25e2e95 Mon Sep 17 00:00:00 2001 From: Eskil Queseth Date: Sat, 17 Oct 2020 15:46:30 +0200 Subject: clean up debug prints --- mumd/src/state.rs | 5 ----- 1 file changed, 5 deletions(-) (limited to 'mumd') diff --git a/mumd/src/state.rs b/mumd/src/state.rs index 4f37364..e4552f0 100644 --- a/mumd/src/state.rs +++ b/mumd/src/state.rs @@ -380,8 +380,6 @@ pub fn into_channel(channels: HashMap, users: HashMap) channel_lookup.entry(user.channel).or_insert(Vec::new()).push(user); } - debug!("{:?}", channel_lookup); - for (channel_id, channel) in &channels { let mut walk = Vec::new(); let mut current = *channel_id; @@ -406,9 +404,6 @@ pub fn into_channel(channels: HashMap, users: HashMap) proto_tree.walk_and_add(channel, &channel_lookup, &walk); } - debug!("{:#?}", channels); - debug!("{:#?}", proto_tree); - (&proto_tree).into() } -- cgit v1.2.1 From b10d20a20496eb9287975fc9fd9b688d59896031 Mon Sep 17 00:00:00 2001 From: Eskil Queseth Date: Sat, 17 Oct 2020 16:16:23 +0200 Subject: change status data transfer struct --- mumd/src/state.rs | 74 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 29 deletions(-) (limited to 'mumd') diff --git a/mumd/src/state.rs b/mumd/src/state.rs index e4552f0..4182b6c 100644 --- a/mumd/src/state.rs +++ b/mumd/src/state.rs @@ -28,9 +28,6 @@ pub struct State { connection_info_sender: watch::Sender>, phase_watcher: (watch::Sender, watch::Receiver), - - username: Option, - session_id: Option, } impl State { @@ -44,8 +41,6 @@ impl State { packet_sender, connection_info_sender, phase_watcher: watch::channel(StatePhase::Disconnected), - username: None, - session_id: None, } } @@ -59,13 +54,13 @@ impl State { if !matches!(*self.phase_receiver().borrow(), StatePhase::Connected) { return (false, Err(Error::DisconnectedError)); } - if let Some(server) = &self.server { - if !server.channels().contains_key(&channel_id) { - return (false, Err(Error::InvalidChannelIdError(channel_id))); - } + let server = self.server.as_ref().unwrap(); + if !server.channels().contains_key(&channel_id) { + return (false, Err(Error::InvalidChannelIdError(channel_id))); } + let mut msg = msgs::UserState::new(); - msg.set_session(self.session_id.unwrap()); + msg.set_session(server.session_id.unwrap()); msg.set_channel_id(channel_id); self.packet_sender.send(msg.into()).unwrap(); (false, Ok(None)) @@ -76,8 +71,8 @@ impl State { } (false, Ok(Some(CommandResponse::ChannelList { channels: into_channel( - self.server.as_ref().unwrap().channels().clone(), - self.server.as_ref().unwrap().users().clone()), + self.server.as_ref().unwrap().channels(), + self.server.as_ref().unwrap().users()), })), ) } @@ -90,8 +85,10 @@ impl State { if !matches!(*self.phase_receiver().borrow(), StatePhase::Disconnected) { return (false, Err(Error::AlreadyConnectedError)); } - self.server = Some(Server::new()); - self.username = Some(username); + let mut server = Server::new(); + server.username = Some(username); + server.host = Some(host.clone()); + self.server = Some(server); self.phase_watcher .0 .broadcast(StatePhase::Connecting) @@ -119,11 +116,9 @@ impl State { } ( false, - /*Ok(Some(CommandResponse::Status { - username: self.username.clone(), - server_state: self.server.clone().unwrap(), //guaranteed not to panic because if we are connected, server is guaranteed to be Some - })),*/ - Err(Error::DisconnectedError) + Ok(Some(CommandResponse::Status { + server_state: self.server.as_ref().unwrap().into(), //guaranteed not to panic because if we are connected, server is guaranteed to be Some + })), ) } Command::ServerDisconnect => { @@ -131,8 +126,6 @@ impl State { return (false, Err(Error::DisconnectedError)); } - self.session_id = None; - self.username = None; self.server = None; self.audio.clear_clients(); @@ -152,11 +145,11 @@ impl State { } if !msg.has_name() { warn!("Missing name in initial user state"); - } else if msg.get_name() == self.username.as_ref().unwrap() { - match self.session_id { + } else if msg.get_name() == self.server.as_ref().unwrap().username.as_ref().unwrap() { + match self.server.as_ref().unwrap().session_id { None => { debug!("Found our session id: {}", msg.get_session()); - self.session_id = Some(msg.get_session()); + self.server_mut().unwrap().session_id = Some(msg.get_session()); } Some(session) => { if session != msg.get_session() { @@ -196,8 +189,8 @@ impl State { pub fn server_mut(&mut self) -> Option<&mut Server> { self.server.as_mut() } - pub fn username(&self) -> Option<&String> { - self.username.as_ref() + pub fn username(&self) -> Option<&str> { + self.server.as_ref().map(|e| e.username()).flatten() } } @@ -206,6 +199,11 @@ pub struct Server { channels: HashMap, users: HashMap, pub welcome_text: Option, + + username: Option, + session_id: Option, + + host: Option, } impl Server { @@ -214,6 +212,9 @@ impl Server { channels: HashMap::new(), users: HashMap::new(), welcome_text: None, + username: None, + session_id: None, + host: None } } @@ -271,6 +272,21 @@ impl Server { pub fn users(&self) -> &HashMap { &self.users } + + pub fn username(&self) -> Option<&str> { + self.username.as_ref().map(|e| e.as_str()) + } +} + +impl From<&Server> for mumlib::state::Server { + fn from(server: &Server) -> Self { + mumlib::state::Server { + channels: into_channel(server.channels(), server.users()), + welcome_text: server.welcome_text.clone(), + username: server.username.clone().unwrap(), + host: server.host.as_ref().unwrap().clone() + } + } } #[derive(Clone, Debug, Deserialize, Serialize)] @@ -371,16 +387,16 @@ impl<'a> From<&ProtoTree<'a>> for mumlib::state::Channel { } } -pub fn into_channel(channels: HashMap, users: HashMap) -> mumlib::state::Channel { +pub fn into_channel(channels: &HashMap, users: &HashMap) -> mumlib::state::Channel { let mut walks = Vec::new(); let mut channel_lookup = HashMap::new(); - for (_, user) in &users { + for (_, user) in users { channel_lookup.entry(user.channel).or_insert(Vec::new()).push(user); } - for (channel_id, channel) in &channels { + for (channel_id, channel) in channels { let mut walk = Vec::new(); let mut current = *channel_id; while let Some(next) = channels.get(¤t).unwrap().parent { -- cgit v1.2.1 From c873e4250c58d872763129bff2c0b0e6c91c0a2a Mon Sep 17 00:00:00 2001 From: Eskil Queseth Date: Sat, 17 Oct 2020 18:39:36 +0200 Subject: add pretty printing for mumctl status --- mumd/src/state.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mumd') diff --git a/mumd/src/state.rs b/mumd/src/state.rs index 4182b6c..2ad88ad 100644 --- a/mumd/src/state.rs +++ b/mumd/src/state.rs @@ -87,7 +87,7 @@ impl State { } let mut server = Server::new(); server.username = Some(username); - server.host = Some(host.clone()); + server.host = Some(format!("{}:{}", host, port)); self.server = Some(server); self.phase_watcher .0 -- cgit v1.2.1 From 821107122299eebde5da1223ea328f63782ceac9 Mon Sep 17 00:00:00 2001 From: Eskil Queseth Date: Sat, 17 Oct 2020 20:44:54 +0200 Subject: cargo fmt --- mumd/src/command.rs | 5 +++- mumd/src/main.rs | 41 +++++++++++++++++++---------- mumd/src/state.rs | 76 +++++++++++++++++++++++++++++++++++++---------------- 3 files changed, 84 insertions(+), 38 deletions(-) (limited to 'mumd') diff --git a/mumd/src/command.rs b/mumd/src/command.rs index 57eaaa3..a035a26 100644 --- a/mumd/src/command.rs +++ b/mumd/src/command.rs @@ -8,7 +8,10 @@ use tokio::sync::mpsc; pub async fn handle( state: Arc>, - mut command_receiver: mpsc::UnboundedReceiver<(Command, IpcSender>>)>, + mut command_receiver: mpsc::UnboundedReceiver<( + Command, + IpcSender>>, + )>, ) { debug!("Begin listening for commands"); while let Some(command) = command_receiver.recv().await { diff --git a/mumd/src/main.rs b/mumd/src/main.rs index 3a0d7ec..5ae077a 100644 --- a/mumd/src/main.rs +++ b/mumd/src/main.rs @@ -7,7 +7,7 @@ use crate::network::ConnectionInfo; use crate::state::State; use futures::join; -use ipc_channel::ipc::{IpcSender, IpcOneShotServer}; +use ipc_channel::ipc::{IpcOneShotServer, IpcSender}; use log::*; use mumble_protocol::control::ControlPacket; use mumble_protocol::crypt::ClientCryptState; @@ -27,14 +27,14 @@ async fn main() { // For simplicity we don't deal with re-syncing, real applications would have to. let (crypt_state_sender, crypt_state_receiver) = mpsc::channel::(1); // crypt state should always be consumed before sending a new one let (packet_sender, packet_receiver) = mpsc::unbounded_channel::>(); - let (command_sender, command_receiver) = mpsc::unbounded_channel::<(Command, IpcSender>>)>(); + let (command_sender, command_receiver) = mpsc::unbounded_channel::<( + Command, + IpcSender>>, + )>(); let (connection_info_sender, connection_info_receiver) = watch::channel::>(None); - let state = State::new( - packet_sender, - connection_info_sender, - ); + let state = State::new(packet_sender, connection_info_sender); let state = Arc::new(Mutex::new(state)); let (_, _, _, e) = join!( @@ -49,11 +49,9 @@ async fn main() { connection_info_receiver.clone(), crypt_state_receiver, ), - command::handle( - state, - command_receiver, - ), - spawn_blocking(move || { // IpcSender is blocking + command::handle(state, command_receiver,), + spawn_blocking(move || { + // IpcSender is blocking receive_oneshot_commands(command_sender); }), ); @@ -61,16 +59,31 @@ async fn main() { } fn receive_oneshot_commands( - command_sender: mpsc::UnboundedSender<(Command, IpcSender>>)>, + command_sender: mpsc::UnboundedSender<( + Command, + IpcSender>>, + )>, ) { loop { // create listener - let (server, server_name): (IpcOneShotServer<(Command, IpcSender>>)>, String) = IpcOneShotServer::new().unwrap(); + let (server, server_name): ( + IpcOneShotServer<( + Command, + IpcSender>>, + )>, + String, + ) = IpcOneShotServer::new().unwrap(); fs::write("/var/tmp/mumd-oneshot", &server_name).unwrap(); debug!("Listening to {}", server_name); // receive command and response channel - let (_, conn): (_, (Command, IpcSender>>)) = server.accept().unwrap(); + let (_, conn): ( + _, + ( + Command, + IpcSender>>, + ), + ) = server.accept().unwrap(); debug!("Sending command {:?} to command handler", conn.0); command_sender.send(conn).unwrap(); } diff --git a/mumd/src/state.rs b/mumd/src/state.rs index 2ad88ad..de74a46 100644 --- a/mumd/src/state.rs +++ b/mumd/src/state.rs @@ -6,12 +6,12 @@ use mumble_protocol::control::msgs; use mumble_protocol::control::ControlPacket; use mumble_protocol::voice::Serverbound; use mumlib::command::{Command, CommandResponse}; -use std::net::ToSocketAddrs; -use tokio::sync::{mpsc, watch}; use mumlib::error::Error; +use serde::{Deserialize, Serialize}; use std::collections::hash_map::Entry; use std::collections::HashMap; -use serde::{Serialize, Deserialize}; +use std::net::ToSocketAddrs; +use tokio::sync::{mpsc, watch}; #[derive(Clone, Debug, Eq, PartialEq)] pub enum StatePhase { @@ -69,10 +69,13 @@ impl State { if !matches!(*self.phase_receiver().borrow(), StatePhase::Connected) { return (false, Err(Error::DisconnectedError)); } - (false, Ok(Some(CommandResponse::ChannelList { + ( + false, + Ok(Some(CommandResponse::ChannelList { channels: into_channel( self.server.as_ref().unwrap().channels(), - self.server.as_ref().unwrap().users()), + self.server.as_ref().unwrap().users(), + ), })), ) } @@ -94,7 +97,10 @@ impl State { .broadcast(StatePhase::Connecting) .unwrap(); - let socket_addr = match (host.as_ref(), port).to_socket_addrs().map(|mut e| e.next()) { + let socket_addr = match (host.as_ref(), port) + .to_socket_addrs() + .map(|mut e| e.next()) + { Ok(Some(v)) => v, _ => { warn!("Error parsing server addr"); @@ -214,7 +220,7 @@ impl Server { welcome_text: None, username: None, session_id: None, - host: None + host: None, } } @@ -284,7 +290,7 @@ impl From<&Server> for mumlib::state::Server { channels: into_channel(server.channels(), server.users()), welcome_text: server.welcome_text.clone(), username: server.username.clone().unwrap(), - host: server.host.as_ref().unwrap().clone() + host: server.host.as_ref().unwrap().clone(), } } } @@ -347,28 +353,36 @@ impl Channel { struct ProtoTree<'a> { channel: Option<&'a Channel>, children: HashMap>, - users: Vec<&'a User> + users: Vec<&'a User>, } impl<'a> ProtoTree<'a> { - fn walk_and_add(&mut self, channel: &'a Channel, users: &HashMap>, walk: &[u32]) { + fn walk_and_add( + &mut self, + channel: &'a Channel, + users: &HashMap>, + walk: &[u32], + ) { match walk { [] => unreachable!("nu gick något snett"), &[node] => { let pt = self.children.entry(node).or_insert(ProtoTree { channel: None, children: HashMap::new(), - users: Vec::new() + users: Vec::new(), }); pt.channel = Some(channel); pt.users = users.get(&node).map(|e| e.clone()).unwrap_or(Vec::new()); } longer => { - self.children.entry(longer[0]).or_insert(ProtoTree { - channel: None, - children: HashMap::new(), - users: Vec::new() - }).walk_and_add(channel, users, &walk[1..]); + self.children + .entry(longer[0]) + .or_insert(ProtoTree { + channel: None, + children: HashMap::new(), + users: Vec::new(), + }) + .walk_and_add(channel, users, &walk[1..]); } } } @@ -377,8 +391,15 @@ impl<'a> ProtoTree<'a> { impl<'a> From<&ProtoTree<'a>> for mumlib::state::Channel { fn from(tree: &ProtoTree<'a>) -> Self { let mut c = mumlib::state::Channel::from(tree.channel.unwrap()); - let mut children = tree.children.iter() - .map(|e| (e.1.channel.unwrap().position, mumlib::state::Channel::from(e.1))) + let mut children = tree + .children + .iter() + .map(|e| { + ( + e.1.channel.unwrap().position, + mumlib::state::Channel::from(e.1), + ) + }) .collect::>(); children.sort_by_key(|e| e.0); c.children = children.into_iter().map(|e| e.1).collect(); @@ -387,13 +408,19 @@ impl<'a> From<&ProtoTree<'a>> for mumlib::state::Channel { } } -pub fn into_channel(channels: &HashMap, users: &HashMap) -> mumlib::state::Channel { +pub fn into_channel( + channels: &HashMap, + users: &HashMap, +) -> mumlib::state::Channel { let mut walks = Vec::new(); let mut channel_lookup = HashMap::new(); for (_, user) in users { - channel_lookup.entry(user.channel).or_insert(Vec::new()).push(user); + channel_lookup + .entry(user.channel) + .or_insert(Vec::new()) + .push(user); } for (channel_id, channel) in channels { @@ -413,7 +440,10 @@ pub fn into_channel(channels: &HashMap, users: &HashMap let mut proto_tree = ProtoTree { channel: Some(channels.get(&0).unwrap()), children: HashMap::new(), - users: channel_lookup.get(&0).map(|e| e.clone()).unwrap_or(Vec::new()), + users: channel_lookup + .get(&0) + .map(|e| e.clone()) + .unwrap_or(Vec::new()), }; for (walk, channel) in walks { @@ -431,7 +461,7 @@ impl From<&Channel> for mumlib::state::Channel { max_users: channel.max_users, name: channel.name.clone(), children: Vec::new(), - users: Vec::new() + users: Vec::new(), } } } @@ -537,4 +567,4 @@ impl From<&User> for mumlib::state::User { deaf: user.deaf, } } -} \ No newline at end of file +} -- cgit v1.2.1 From 7d18be093e0952470591fd130417ad13c941318e Mon Sep 17 00:00:00 2001 From: Eskil Queseth Date: Sat, 17 Oct 2020 20:54:12 +0200 Subject: changes according to feedback --- mumd/src/state.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'mumd') diff --git a/mumd/src/state.rs b/mumd/src/state.rs index de74a46..e7b0233 100644 --- a/mumd/src/state.rs +++ b/mumd/src/state.rs @@ -364,7 +364,7 @@ impl<'a> ProtoTree<'a> { walk: &[u32], ) { match walk { - [] => unreachable!("nu gick något snett"), + [] => unreachable!("shouldn't happen because walks always have at least one element"), &[node] => { let pt = self.children.entry(node).or_insert(ProtoTree { channel: None, @@ -390,7 +390,7 @@ impl<'a> ProtoTree<'a> { impl<'a> From<&ProtoTree<'a>> for mumlib::state::Channel { fn from(tree: &ProtoTree<'a>) -> Self { - let mut c = mumlib::state::Channel::from(tree.channel.unwrap()); + let mut channel = mumlib::state::Channel::from(tree.channel.unwrap()); let mut children = tree .children .iter() @@ -401,10 +401,10 @@ impl<'a> From<&ProtoTree<'a>> for mumlib::state::Channel { ) }) .collect::>(); - children.sort_by_key(|e| e.0); - c.children = children.into_iter().map(|e| e.1).collect(); - c.users = tree.users.iter().map(|e| (*e).into()).collect(); - c + children.sort_by_key(|e| (e.0, &e.1.name)); + channel.children = children.into_iter().map(|e| e.1).collect(); + channel.users = tree.users.iter().map(|e| (*e).into()).collect(); + channel } } @@ -416,7 +416,7 @@ pub fn into_channel( let mut channel_lookup = HashMap::new(); - for (_, user) in users { + for user in users.values() { channel_lookup .entry(user.channel) .or_insert(Vec::new()) -- cgit v1.2.1 From 9cfdbf0c68e544dbaa67da7e5620f4099d1c718e Mon Sep 17 00:00:00 2001 From: Eskil Queseth Date: Sat, 17 Oct 2020 20:55:41 +0200 Subject: add comment --- mumd/src/state.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'mumd') diff --git a/mumd/src/state.rs b/mumd/src/state.rs index e7b0233..94a0293 100644 --- a/mumd/src/state.rs +++ b/mumd/src/state.rs @@ -437,6 +437,7 @@ pub fn into_channel( } } + //root node is ignored because of how walk_and_add is implemented on ProtoTree let mut proto_tree = ProtoTree { channel: Some(channels.get(&0).unwrap()), children: HashMap::new(), -- cgit v1.2.1 From f16f51f5ec41b5a3472f0639bd0324cd339fa21e Mon Sep 17 00:00:00 2001 From: Eskil Queseth Date: Sat, 17 Oct 2020 20:59:25 +0200 Subject: fix oopsie --- mumd/src/state.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mumd') diff --git a/mumd/src/state.rs b/mumd/src/state.rs index 94a0293..2515cb7 100644 --- a/mumd/src/state.rs +++ b/mumd/src/state.rs @@ -401,7 +401,7 @@ impl<'a> From<&ProtoTree<'a>> for mumlib::state::Channel { ) }) .collect::>(); - children.sort_by_key(|e| (e.0, &e.1.name)); + children.sort_by_key(|e| (e.0, e.1.name.clone())); channel.children = children.into_iter().map(|e| e.1).collect(); channel.users = tree.users.iter().map(|e| (*e).into()).collect(); channel -- cgit v1.2.1 From f1df606dfeafbfe93066d23f378d7fdbd1b4e9e1 Mon Sep 17 00:00:00 2001 From: Eskil Date: Sat, 17 Oct 2020 19:02:28 +0000 Subject: Apply 1 suggestion(s) to 1 file(s) --- mumd/src/state.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mumd') diff --git a/mumd/src/state.rs b/mumd/src/state.rs index 2515cb7..1c964b3 100644 --- a/mumd/src/state.rs +++ b/mumd/src/state.rs @@ -364,7 +364,7 @@ impl<'a> ProtoTree<'a> { walk: &[u32], ) { match walk { - [] => unreachable!("shouldn't happen because walks always have at least one element"), + [] => unreachable!("Walks should always have at least one element"), &[node] => { let pt = self.children.entry(node).or_insert(ProtoTree { channel: None, -- cgit v1.2.1