use crate::common::device::DeviceInfo;
use crate::common::protocol::{Frame, SystemCommand};
use crate::common::protocol::flare::core::commands::system_command::SerializationFormat;
use crate::common::compression::CompressionAlgorithm;
use crate::common::error::Result;
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub struct NegotiationResult {
pub serialization_format: SerializationFormat,
pub compression: CompressionAlgorithm,
pub is_forced: bool,
pub device_info: Option<DeviceInfo>,
pub user_id: Option<String>,
}
impl NegotiationResult {
pub fn default() -> Self {
Self {
serialization_format: SerializationFormat::Json,
compression: CompressionAlgorithm::None,
is_forced: false,
device_info: None,
user_id: None,
}
}
}
pub fn parse_connect_message(frame: &Frame) -> Result<NegotiationResult> {
let mut result = NegotiationResult::default();
if let Some(cmd) = &frame.command {
if let Some(crate::common::protocol::flare::core::commands::command::Type::System(sys_cmd)) = &cmd.r#type {
use crate::common::protocol::flare::core::commands::system_command::Type as SystemType;
if sys_cmd.r#type == SystemType::Connect as i32 {
result.serialization_format = SerializationFormat::from_i32(sys_cmd.format)
.unwrap_or(SerializationFormat::Json);
if let Some(compression_bytes) = sys_cmd.metadata.get("compression") {
if let Ok(compression_str) = String::from_utf8(compression_bytes.clone()) {
result.compression = CompressionAlgorithm::from_str(&compression_str)
.unwrap_or(CompressionAlgorithm::None);
}
}
if let Some(device_id_bytes) = sys_cmd.metadata.get("device_id") {
if let Ok(device_id) = String::from_utf8(device_id_bytes.clone()) {
let platform = if let Some(platform_bytes) = sys_cmd.metadata.get("platform") {
if let Ok(platform_str) = String::from_utf8(platform_bytes.clone()) {
crate::common::device::DevicePlatform::from_str(&platform_str)
} else {
crate::common::device::DevicePlatform::Other("unknown".to_string())
}
} else {
crate::common::device::DevicePlatform::Other("unknown".to_string())
};
let mut device_info = DeviceInfo::new(device_id, platform);
if let Some(model_bytes) = sys_cmd.metadata.get("model") {
if let Ok(model) = String::from_utf8(model_bytes.clone()) {
device_info = device_info.with_model(model);
}
}
if let Some(app_version_bytes) = sys_cmd.metadata.get("app_version") {
if let Ok(app_version) = String::from_utf8(app_version_bytes.clone()) {
device_info = device_info.with_app_version(app_version);
}
}
if let Some(system_version_bytes) = sys_cmd.metadata.get("system_version") {
if let Ok(system_version) = String::from_utf8(system_version_bytes.clone()) {
device_info = device_info.with_system_version(system_version);
}
}
for (key, value) in &sys_cmd.metadata {
if !matches!(key.as_str(), "compression" | "device_id" | "platform" | "model" | "app_version" | "system_version" | "user_id") {
if let Ok(value_str) = String::from_utf8(value.clone()) {
device_info = device_info.with_metadata(key.clone(), value_str);
}
}
}
result.device_info = Some(device_info);
}
}
if let Some(user_id_bytes) = sys_cmd.metadata.get("user_id") {
if let Ok(user_id) = String::from_utf8(user_id_bytes.clone()) {
result.user_id = Some(user_id);
}
}
if let Some(force_bytes) = sys_cmd.metadata.get("force_format") {
if let Ok(force_str) = String::from_utf8(force_bytes.clone()) {
result.is_forced = force_str == "true";
}
}
}
}
}
Ok(result)
}
pub fn create_connect_ack(
format: SerializationFormat,
compression: CompressionAlgorithm,
additional_metadata: Option<HashMap<String, Vec<u8>>>,
) -> SystemCommand {
let mut metadata = HashMap::new();
metadata.insert("compression".to_string(), compression.as_str().as_bytes().to_vec());
if let Some(extra) = additional_metadata {
for (key, value) in extra {
metadata.insert(key, value);
}
}
crate::common::protocol::connect_ack(format, metadata)
}