kojacoord_protocol/
negotiation.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2pub enum ProtocolVersion {
3 V1_6_4,
4
5 V1_7_10,
6
7 V1_8,
8
9 V1_12_2,
10
11 V1_16_5,
12
13 V1_19_4,
14
15 V1_20_4,
16
17 V1_21,
18
19 Unknown(u32),
20}
21
22impl ProtocolVersion {
23 pub fn from_id(id: u32) -> Self {
24 match id {
25 5 => ProtocolVersion::V1_7_10,
26 47 => ProtocolVersion::V1_8,
27 78 => ProtocolVersion::V1_6_4,
28 340 => ProtocolVersion::V1_12_2,
29 754 => ProtocolVersion::V1_16_5,
30 762 => ProtocolVersion::V1_19_4,
31 765 => ProtocolVersion::V1_20_4,
32 767 => ProtocolVersion::V1_21,
33 x => ProtocolVersion::Unknown(x),
34 }
35 }
36
37 pub fn id(&self) -> u32 {
38 match self {
39 ProtocolVersion::V1_6_4 => 78,
40 ProtocolVersion::V1_7_10 => 5,
41 ProtocolVersion::V1_8 => 47,
42 ProtocolVersion::V1_12_2 => 340,
43 ProtocolVersion::V1_16_5 => 754,
44 ProtocolVersion::V1_19_4 => 762,
45 ProtocolVersion::V1_20_4 => 765,
46 ProtocolVersion::V1_21 => 767,
47 ProtocolVersion::Unknown(x) => *x,
48 }
49 }
50
51 pub fn is_supported(&self) -> bool {
52 !matches!(self, ProtocolVersion::Unknown(_))
53 }
54}
55
56pub struct VersionRegistry;
57
58impl VersionRegistry {
59 const SUPPORTED: &'static [u32] = &[5, 47, 78, 340, 754, 762, 765, 767];
60
61 pub fn nearest(protocol_id: u32) -> ProtocolVersion {
62 let exact = ProtocolVersion::from_id(protocol_id);
63 if exact.is_supported() {
64 return exact;
65 }
66
67 let best = Self::SUPPORTED
68 .iter()
69 .copied()
70 .min_by_key(|&s| (s as i64 - protocol_id as i64).unsigned_abs())
71 .unwrap_or(767);
72
73 ProtocolVersion::from_id(best)
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn known_versions_roundtrip() {
83 for &id in VersionRegistry::SUPPORTED {
84 let v = ProtocolVersion::from_id(id);
85 assert!(v.is_supported());
86 assert_eq!(v.id(), id);
87 }
88 }
89
90 #[test]
91 fn v1_7_10_recognized() {
92 assert_eq!(ProtocolVersion::from_id(5), ProtocolVersion::V1_7_10);
93 }
94
95 #[test]
96 fn v1_6_4_recognized() {
97 assert_eq!(ProtocolVersion::from_id(78), ProtocolVersion::V1_6_4);
98 }
99
100 #[test]
101 fn nearest_exact() {
102 assert_eq!(VersionRegistry::nearest(47), ProtocolVersion::V1_8);
103 assert_eq!(VersionRegistry::nearest(5), ProtocolVersion::V1_7_10);
104 }
105
106 #[test]
107 fn nearest_between_versions() {
108 let v = VersionRegistry::nearest(400);
109 assert_eq!(v, ProtocolVersion::V1_12_2);
110 }
111}