iscp/transport/
negotiation.rs1use bytes::BufMut;
2
3use crate::encoding;
4use crate::transport::TransportError;
5
6#[derive(Clone, Debug, serde::Serialize)]
8#[non_exhaustive]
9pub enum EncodingName {
10 #[serde(rename = "proto")]
11 Protobuf,
12}
13
14impl From<encoding::Name> for EncodingName {
15 fn from(name: encoding::Name) -> Self {
16 match name {
17 encoding::Name::Protobuf => EncodingName::Protobuf,
18 }
19 }
20}
21
22#[derive(Clone, Debug, serde::Serialize)]
24pub enum CompressionType {
25 #[serde(rename = "per-message")]
26 PerMessage,
27 #[serde(rename = "context-takeover")]
28 ContextTakeover,
29}
30
31#[derive(Clone, Debug, serde::Serialize)]
33#[non_exhaustive]
34pub struct NegotiationParams {
35 #[serde(rename = "enc")]
36 pub encoding_name: EncodingName,
37 #[serde(rename = "comp", skip_serializing_if = "Option::is_none")]
38 pub compression_type: Option<CompressionType>,
39 #[serde(rename = "clevel", skip_serializing_if = "Option::is_none")]
40 pub compression_level: Option<i8>,
41 #[serde(rename = "cwinbits", skip_serializing_if = "Option::is_none")]
42 pub compression_window_bits: Option<u8>,
43}
44
45impl NegotiationParams {
46 pub(crate) fn to_uri_query_string(&self) -> Result<String, TransportError> {
47 serde_qs::to_string(&self).map_err(TransportError::new)
48 }
49
50 pub(crate) fn to_bytes(&self) -> Result<Vec<u8>, TransportError> {
51 use serde_json::Value;
52
53 let mut buf = Vec::new();
54
55 let value = serde_json::to_value(self).unwrap();
56 let map = value.as_object().unwrap();
57 for (k, v) in map.iter() {
58 let v = match v {
59 Value::Null => continue,
60 Value::String(s) => s.clone(),
61 _ => v.to_string(),
62 };
63
64 buf.put_u16(
65 k.len()
66 .try_into()
67 .map_err(|_| TransportError::from_msg("too long key for negotiation"))?,
68 );
69 buf.put(k.as_bytes());
70
71 buf.put_u16(
72 v.len()
73 .try_into()
74 .map_err(|_| TransportError::from_msg("too long value for negotiation"))?,
75 );
76 buf.put(v.as_bytes());
77 }
78
79 Ok(buf)
80 }
81}