memlink_protocol/
negotiation.rs1use crate::error::{ProtocolError, Result};
7use crate::features::intersect_features;
8use crate::version::{ProtocolVersion, SUPPORTED_VERSIONS};
9
10pub fn negotiate_version(client: &ProtocolVersion, server: &ProtocolVersion) -> Result<ProtocolVersion> {
11 if client.major() != server.major() {
12 return Err(ProtocolError::UnsupportedVersion(
13 client.major().max(server.major()) as u8,
14 ));
15 }
16
17 let negotiated_minor = client.minor().min(server.minor());
18 let common_features = intersect_features(client.features(), server.features());
19
20 Ok(ProtocolVersion::new(client.major(), negotiated_minor, common_features))
21}
22
23pub fn negotiate_with_server_versions(
24 client: &ProtocolVersion,
25 server_versions: &[ProtocolVersion],
26) -> Result<ProtocolVersion> {
27 let mut best_version: Option<ProtocolVersion> = None;
28
29 for server_version in server_versions {
30 if let Ok(negotiated) = negotiate_version(client, server_version) {
31 if best_version.is_none() || negotiated.compare(&best_version.unwrap()) > 0 {
32 best_version = Some(negotiated);
33 }
34 }
35 }
36
37 best_version.ok_or_else(|| ProtocolError::UnsupportedVersion(client.major() as u8))
38}
39
40pub fn validate_version(version: &ProtocolVersion) -> Result<()> {
41 for supported in SUPPORTED_VERSIONS {
42 if version.major() == supported.major() && version.minor() <= supported.minor() {
43 return Ok(());
44 }
45 }
46
47 Err(ProtocolError::UnsupportedVersion(version.major() as u8))
48}
49
50pub fn is_feature_supported(feature: u32) -> bool {
51 feature != 0 && feature <= 0x00000007
52}
53
54pub fn version_string(version: &ProtocolVersion) -> alloc::string::String {
55 use alloc::format;
56 format!("MemLink/{}.{}", version.major(), version.minor())
57}