saito_core/core/consensus/peers/
peer_service.rs

1use std::io::{Error, ErrorKind};
2
3use log::{error, warn};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct PeerService {
8    pub service: String,
9    pub domain: String,
10    pub name: String,
11    // TODO: add versioning info here for application services for #622
12}
13
14impl TryFrom<String> for PeerService {
15    type Error = std::io::Error;
16
17    fn try_from(value: String) -> Result<PeerService, std::io::Error> {
18        let values: Vec<&str> = value.split('|').collect();
19        if values.len() != 3 {
20            return Err(Error::from(ErrorKind::InvalidData));
21        }
22        let service = values[0].try_into();
23        let domain = values[1].try_into();
24        let name = values[2].try_into();
25        if service.is_err() {
26            return Err(Error::from(ErrorKind::InvalidData));
27        }
28        if domain.is_err() {
29            return Err(Error::from(ErrorKind::InvalidData));
30        }
31        if name.is_err() {
32            return Err(Error::from(ErrorKind::InvalidData));
33        }
34        Ok(PeerService {
35            service: service.unwrap(),
36            domain: domain.unwrap(),
37            name: name.unwrap(),
38        })
39    }
40}
41
42impl Into<String> for PeerService {
43    fn into(self) -> String {
44        self.service + "|" + self.domain.as_str() + "|" + self.name.as_str()
45    }
46}
47
48impl PeerService {
49    pub fn serialize_services(services: &Vec<PeerService>) -> Vec<u8> {
50        if services.is_empty() {
51            return vec![];
52        }
53        let str: String = services
54            .iter()
55            .map(|service| {
56                let str: String = service.clone().into();
57                str
58            })
59            .collect::<Vec<String>>()
60            .join(";");
61        str.as_bytes().to_vec()
62    }
63    pub fn deserialize_services(buffer: Vec<u8>) -> Result<Vec<PeerService>, Error> {
64        if buffer.is_empty() {
65            return Ok(vec![]);
66        }
67        let str = String::from_utf8(buffer);
68        if str.is_err() {
69            warn!("failed parsing services.");
70            error!("{:?}", str.err().unwrap());
71            return Err(Error::from(ErrorKind::InvalidData));
72        }
73        let str = str.unwrap();
74        let strings = str.split(";");
75        let mut services: Vec<PeerService> = Default::default();
76        for str in strings {
77            if str.is_empty() {
78                continue;
79            }
80            let result = str.try_into();
81            if result.is_err() {
82                warn!("cannot parse services from : {:?}", str);
83                return Err(Error::from(ErrorKind::InvalidData));
84            }
85            let result: String = result.unwrap();
86            let service = result.try_into();
87
88            if service.is_err() {
89                warn!("cannot parse services from : {:?}", str);
90                return Err(Error::from(ErrorKind::InvalidData));
91            }
92
93            services.push(service.unwrap());
94        }
95        Ok(services)
96    }
97}
98
99#[cfg(test)]
100mod tests {
101    use crate::core::consensus::peers::peer_service::PeerService;
102
103    #[test]
104    fn test_serialize() {
105        let mut services = vec![];
106        services.push(PeerService {
107            service: "service1".to_string(),
108            domain: "domain1".to_string(),
109            name: "name1".to_string(),
110        });
111        services.push(PeerService {
112            service: "service2".to_string(),
113            domain: "".to_string(),
114            name: "name2".to_string(),
115        });
116        services.push(PeerService {
117            service: "service3".to_string(),
118            domain: "domain3".to_string(),
119            name: "".to_string(),
120        });
121        services.push(PeerService {
122            service: "service4".to_string(),
123            domain: "".to_string(),
124            name: "".to_string(),
125        });
126
127        let buffer = PeerService::serialize_services(&services);
128
129        assert!(buffer.len() > 0);
130
131        let result = PeerService::deserialize_services(buffer);
132        assert!(result.is_ok());
133        let services = result.unwrap();
134        assert_eq!(services.len(), 4);
135
136        let service = services.get(0).unwrap();
137        assert_eq!(service.service, "service1");
138        assert_eq!(service.domain, "domain1");
139        assert_eq!(service.name, "name1");
140
141        let service = services.get(1).unwrap();
142        assert_eq!(service.service, "service2");
143        assert_eq!(service.domain, "");
144        assert_eq!(service.name, "name2");
145
146        let service = services.get(2).unwrap();
147        assert_eq!(service.service, "service3");
148        assert_eq!(service.domain, "domain3");
149        assert_eq!(service.name, "");
150
151        let service = services.get(3).unwrap();
152        assert_eq!(service.service, "service4");
153        assert_eq!(service.domain, "");
154        assert_eq!(service.name, "");
155    }
156}