1use crate::state::user::User;
2
3use mumble_protocol::control::msgs;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7#[derive(Clone, Debug, Default, Deserialize, Serialize)]
8pub struct Channel {
9 description: Option<String>,
10 links: Vec<u32>,
11 max_users: u32,
12 name: String,
13 parent: Option<u32>,
14 position: i32,
15}
16
17impl Channel {
18 pub fn new(mut msg: msgs::ChannelState) -> Self {
19 Self {
20 description: if msg.has_description() {
21 Some(msg.take_description())
22 } else {
23 None
24 },
25 links: Vec::new(),
26 max_users: msg.get_max_users(),
27 name: msg.take_name(),
28 parent: if msg.has_parent() {
29 Some(msg.get_parent())
30 } else {
31 None
32 },
33 position: msg.get_position(),
34 }
35 }
36
37 pub fn parse_channel_state(&mut self, mut msg: msgs::ChannelState) {
38 if msg.has_description() {
39 self.description = Some(msg.take_description());
40 }
41 self.links = msg.take_links();
42 if msg.has_max_users() {
43 self.max_users = msg.get_max_users();
44 }
45 if msg.has_name() {
46 self.name = msg.take_name();
47 }
48 if msg.has_parent() {
49 self.parent = Some(msg.get_parent());
50 }
51 if msg.has_position() {
52 self.position = msg.get_position();
53 }
54 }
55
56 pub fn name(&self) -> &str {
57 &self.name
58 }
59
60 pub fn path(&self, channels: &HashMap<u32, Channel>) -> String {
61 match &self.parent {
62 Some(t) => format!("{}/{}", channels.get(t).unwrap().path(channels), self.name),
63 None => self.name.clone(),
64 }
65 }
66}
67
68#[derive(Debug)]
69struct ProtoTree<'a> {
70 channel: Option<&'a Channel>,
71 children: HashMap<u32, ProtoTree<'a>>,
72 users: Vec<&'a User>,
73}
74
75impl<'a> ProtoTree<'a> {
76 fn walk_and_add(
77 &mut self,
78 channel: &'a Channel,
79 users: &HashMap<u32, Vec<&'a User>>,
80 walk: &[u32],
81 ) {
82 match walk {
83 [] => unreachable!("Walks should always have at least one element"),
84 &[node] => {
85 let pt = self.children.entry(node).or_insert(ProtoTree {
86 channel: None,
87 children: HashMap::new(),
88 users: Vec::new(),
89 });
90 pt.channel = Some(channel);
91 pt.users = users.get(&node).cloned().unwrap_or_default();
92 }
93 longer => {
94 self.children
95 .entry(longer[0])
96 .or_insert(ProtoTree {
97 channel: None,
98 children: HashMap::new(),
99 users: Vec::new(),
100 })
101 .walk_and_add(channel, users, &walk[1..]);
102 }
103 }
104 }
105}
106
107impl<'a> From<&ProtoTree<'a>> for mumlib::state::Channel {
108 fn from(tree: &ProtoTree<'a>) -> Self {
109 let mut channel = mumlib::state::Channel::from(tree.channel.unwrap());
110 let mut children = tree
111 .children
112 .iter()
113 .map(|e| {
114 (
115 e.1.channel.unwrap().position,
116 mumlib::state::Channel::from(e.1),
117 )
118 })
119 .collect::<Vec<_>>();
120 children.sort_by_key(|e| (e.0, e.1.name.clone()));
121 channel.children = children.into_iter().map(|e| e.1).collect();
122 channel.users = tree.users.iter().map(|e| (*e).into()).collect();
123 channel
124 }
125}
126
127pub fn into_channel(
128 channels: &HashMap<u32, Channel>,
129 users: &HashMap<u32, User>,
130) -> mumlib::state::Channel {
131 let mut walks = Vec::new();
132
133 let mut channel_lookup = HashMap::new();
134
135 for user in users.values() {
136 channel_lookup
137 .entry(user.channel())
138 .or_insert_with(Vec::new)
139 .push(user);
140 }
141
142 for (channel_id, channel) in channels {
143 let mut walk = Vec::new();
144 let mut current = *channel_id;
145 while let Some(next) = channels.get(¤t).unwrap().parent {
146 walk.push(current);
147 current = next;
148 }
149 walk.reverse();
150
151 if !walk.is_empty() {
152 walks.push((walk, channel));
153 }
154 }
155
156 let mut proto_tree = ProtoTree {
158 channel: Some(channels.get(&0).unwrap()),
159 children: HashMap::new(),
160 users: channel_lookup.get(&0).cloned().unwrap_or_default(),
161 };
162
163 for (walk, channel) in walks {
164 proto_tree.walk_and_add(channel, &channel_lookup, &walk);
165 }
166
167 (&proto_tree).into()
168}
169
170impl From<&Channel> for mumlib::state::Channel {
171 fn from(channel: &Channel) -> Self {
172 mumlib::state::Channel::new(
173 channel.name.clone(),
174 channel.description.clone(),
175 channel.max_users,
176 )
177 }
178}