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
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
//! `tsproto-types` contains basic types and enums that are used within the TeamSpeak protocol.

use std::borrow::{Borrow, Cow};
use std::fmt;
use std::u64;

use bitflags::bitflags;
use num_derive::{FromPrimitive, ToPrimitive};
use ref_cast::RefCast;
use serde::{Deserialize, Deserializer, Serialize};
use time::OffsetDateTime;

pub mod crypto;
pub mod errors;
pub mod versions;

include!(concat!(env!("OUT_DIR"), "/enums.rs"));

/// A `ClientId` identifies a client which is connected to a server.
///
/// Every client that we see on a server has a `ClientId`, even our own
/// connection.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct ClientId(pub u16);
/// Describes a client or server uid which is a base64
/// encoded hash or a special reserved name.
///
/// This is saved raw, so the base64-decoded TeamSpeak uid.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct UidBuf(pub Vec<u8>);

#[derive(Debug, Eq, PartialEq, RefCast, Serialize)]
#[repr(transparent)]
pub struct Uid(pub [u8]);

impl ToOwned for Uid {
	type Owned = UidBuf;
	fn to_owned(&self) -> Self::Owned { UidBuf(self.0.to_owned()) }
}
impl Borrow<Uid> for UidBuf {
	fn borrow(&self) -> &Uid { Uid::ref_cast(self.0.borrow()) }
}
impl AsRef<Uid> for UidBuf {
	fn as_ref(&self) -> &Uid { self.borrow() }
}
impl core::ops::Deref for UidBuf {
	type Target = Uid;
	fn deref(&self) -> &Self::Target { self.borrow() }
}
impl<'a> From<&'a Uid> for Cow<'a, Uid> {
	fn from(u: &'a Uid) -> Self { Cow::Borrowed(u) }
}

impl Uid {
	pub fn from_bytes(data: &'_ [u8]) -> &Self { Uid::ref_cast(data) }

	/// TeamSpeak uses a different encoding of the uid for fetching avatars.
	///
	/// The raw data (base64-decoded) is encoded in hex, but instead of using
	/// [0-9a-f] with [a-p].
	pub fn as_avatar(&self) -> String {
		let mut res = String::with_capacity(self.0.len() * 2);
		for b in &self.0 {
			res.push((b'a' + (b >> 4)) as char);
			res.push((b'a' + (b & 0xf)) as char);
		}
		res
	}

	pub fn is_server_admin(&self) -> bool { &self.0 == b"ServerAdmin" }
}

impl<'a, 'de: 'a> Deserialize<'de> for &'a Uid {
	fn deserialize<D>(d: D) -> Result<&'a Uid, D::Error>
	where D: Deserializer<'de> {
		let data = <&[u8]>::deserialize(d)?;
		Ok(Uid::from_bytes(data))
	}
}

/// The database id of a client.
///
/// This is the id which is saved for a client in the database of one specific
/// server.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct ClientDbId(pub u64);

/// Identifies a channel on a server.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct ChannelId(pub u64);

/// Identifies a server group on a server.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct ServerGroupId(pub u64);

/// Identifies a channel group on a server.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct ChannelGroupId(pub u64);

#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct IconId(pub u32);

#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct Permission(pub u32);
impl Permission {
	/// Never fails
	pub fn from_u32(i: u32) -> Option<Self> { Some(Permission(i)) }
	/// Never fails
	pub fn to_u32(self) -> Option<u32> { Some(self.0) }
}

#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum ClientType {
	Normal,
	/// Server query client
	Query {
		admin: bool,
	},
}

#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum MaxClients {
	Unlimited,
	Inherited,
	Limited(u16),
}

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct TalkPowerRequest {
	pub time: OffsetDateTime,
	pub message: String,
}

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct Invoker {
	pub name: String,
	pub id: ClientId,
	pub uid: Option<UidBuf>,
}

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct InvokerRef<'a> {
	pub name: &'a str,
	pub id: ClientId,
	pub uid: Option<&'a Uid>,
}

impl Invoker {
	pub fn as_ref(&self) -> InvokerRef {
		InvokerRef { name: &self.name, id: self.id, uid: self.uid.as_ref().map(|u| u.as_ref()) }
	}
}

impl fmt::Display for ClientId {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.0) }
}
impl fmt::Display for Uid {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "{}", base64::encode(&self.0))
	}
}
impl fmt::Display for ClientDbId {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.0) }
}
impl fmt::Display for ChannelId {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.0) }
}
impl fmt::Display for ServerGroupId {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.0) }
}
impl fmt::Display for ChannelGroupId {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.0) }
}