Skip to main content

iscp/transport/
negotiation.rs

1use bytes::BufMut;
2
3use crate::encoding;
4use crate::transport::TransportError;
5
6/// エンコード方法
7#[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/// 圧縮タイプ
23#[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/// 接続開始時のパラメータ
32#[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}