cyfs_base/objects/
area.rs

1use crate::codec::{RawDecode, RawEncode, RawEncodePurpose, RawFixedBytes};
2use crate::*;
3use std::fmt::{Display, Formatter};
4use std::str::FromStr;
5// use crate::{ObjectType, ObjectTypeCode, ObjectId};
6
7#[derive(Eq, PartialEq, Clone, Debug)]
8pub struct Area {
9    pub country: u16,
10    pub carrier: u8,
11    pub city: u16,
12    pub inner: u8, //对不同的对象来说有不同的意义,比如device这里就表示 device的设备类型。
13                   //分类:OOD、server、pc、路由器、android mobile、android pad、android watch、Android  TV
14                   //    iOS mobile、iOS pad、iOS watch、
15                   //    智能音箱
16                   //    浏览器
17                   //    IoT 传感器
18                   //    智能家具设备
19}
20
21impl Area {
22    pub fn new(country: u16, carrier: u8, city: u16, inner: u8) -> Self {
23        assert!(country <= 0x1FF);
24        assert!(city <= 0x1FFF);
25        assert!(carrier <= 0xF);
26        Area {
27            country,
28            carrier,
29            city,
30            inner,
31        }
32    }
33}
34
35impl FromStr for Area {
36    type Err = BuckyError;
37
38    fn from_str(s: &str) -> Result<Self, Self::Err> {
39        let values = s.split(":");
40        let mut array: Vec<u16> = vec![];
41        for value in values {
42            match value.parse::<u16>() {
43                Ok(num) => array.push(num),
44                Err(_) => {
45                    return Err(BuckyError::new(
46                        BuckyErrorCode::InvalidFormat,
47                        "decode area err",
48                    ))
49                }
50            }
51        }
52        if array.len() != 4 {
53            return Err(BuckyError::new(
54                BuckyErrorCode::InvalidFormat,
55                "decode area err",
56            ));
57        }
58        if array[0] > 0x1FF || array[2] > 0x1FFF || array[1] > 0xF {
59            return Err(BuckyError::new(
60                BuckyErrorCode::InvalidFormat,
61                "decode area err",
62            ));
63        }
64
65        Ok(Area {
66            country: array[0],
67            carrier: array[1] as u8,
68            city: array[2],
69            inner: array[3] as u8,
70        })
71    }
72}
73
74impl Display for Area {
75    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
76        write!(
77            f,
78            "{}:{}:{}:{}",
79            self.country, self.carrier, self.city, self.inner
80        )
81    }
82}
83
84impl Default for Area {
85    fn default() -> Self {
86        Area {
87            country: 0,
88            carrier: 0,
89            city: 0,
90            inner: 0,
91        }
92    }
93}
94
95impl RawFixedBytes for Area {
96    fn raw_bytes() -> Option<usize> {
97        Some(5)
98    }
99}
100
101impl RawEncode for Area {
102    fn raw_measure(&self, _purpose: &Option<RawEncodePurpose>) -> Result<usize, BuckyError> {
103        Ok(5)
104    }
105
106    fn raw_encode<'a>(
107        &self,
108        buf: &'a mut [u8],
109        _purpose: &Option<RawEncodePurpose>,
110    ) -> Result<&'a mut [u8], BuckyError> {
111        let bytes = Self::raw_bytes().unwrap();
112        if buf.len() < bytes {
113            let msg = format!(
114                "not enough buffer for encode Area, except={}, got={}",
115                bytes,
116                buf.len()
117            );
118            error!("{}", msg);
119
120            return Err(BuckyError::new(BuckyErrorCode::OutOfLimit, msg));
121        }
122
123        // (国家编码9bits)+(运营商编码4bits)+城市编码(13bits)+inner(8bits) = 34 bit
124        // 此处直接用5个bytes
125        buf[0] = self.country as u8;
126        buf[1] = self.carrier;
127        buf[2] = (self.city >> 8) as u8 | (self.country >> 8 << 7) as u8;
128        buf[3] = (self.city << 8 >> 8) as u8;
129        buf[4] = self.inner;
130
131        Ok(&mut buf[5..])
132    }
133}
134
135impl<'de> RawDecode<'de> for Area {
136    fn raw_decode(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> {
137        let bytes = Self::raw_bytes().unwrap();
138        if buf.len() < bytes {
139            let msg = format!(
140                "not enough buffer for decode Area, except={}, got={}",
141                bytes,
142                buf.len()
143            );
144            error!("{}", msg);
145
146            return Err(BuckyError::new(BuckyErrorCode::OutOfLimit, msg));
147        }
148
149        let mut area_code = Self::default();
150        area_code.country = buf[0] as u16 | (buf[2] as u16 >> 7 << 8);
151        area_code.carrier = buf[1];
152        area_code.city = ((buf[2] as u16) << 9 >> 1) | (buf[3] as u16);
153        area_code.inner = buf[4];
154
155        Ok((area_code, &buf[5..]))
156    }
157}
158
159#[cfg(test)]
160mod test_area {
161    use crate::*;
162    use std::str::FromStr;
163
164    #[test]
165    fn test() {
166        let area = Area::new(333, 14, 3345, 32);
167        let buf = area.to_vec().unwrap();
168        let tmp_area = Area::clone_from_slice(buf.as_slice()).unwrap();
169
170        assert_eq!(333, tmp_area.country);
171        assert_eq!(14, tmp_area.carrier);
172        assert_eq!(3345, tmp_area.city);
173        assert_eq!(32, tmp_area.inner);
174        assert_eq!(area.country, tmp_area.country);
175        assert_eq!(area.carrier, tmp_area.carrier);
176        assert_eq!(area.city, tmp_area.city);
177        assert_eq!(area.inner, tmp_area.inner);
178
179        let area = Area::new(33, 14, 3345, 32);
180        let buf = area.to_vec().unwrap();
181        let tmp_area = Area::clone_from_slice(buf.as_slice()).unwrap();
182
183        assert_eq!(33, tmp_area.country);
184        assert_eq!(14, tmp_area.carrier);
185        assert_eq!(3345, tmp_area.city);
186        assert_eq!(32, tmp_area.inner);
187        assert_eq!(area.country, tmp_area.country);
188        assert_eq!(area.carrier, tmp_area.carrier);
189        assert_eq!(area.city, tmp_area.city);
190        assert_eq!(area.inner, tmp_area.inner);
191    }
192
193    #[test]
194    fn test_str() {
195        let area = Area::from_str("333:14:3345:32").unwrap();
196        let buf = area.to_vec().unwrap();
197        let tmp_area = Area::clone_from_slice(buf.as_slice()).unwrap();
198
199        assert_eq!(333, tmp_area.country);
200        assert_eq!(14, tmp_area.carrier);
201        assert_eq!(3345, tmp_area.city);
202        assert_eq!(32, tmp_area.inner);
203        assert_eq!(area.country, tmp_area.country);
204        assert_eq!(area.carrier, tmp_area.carrier);
205        assert_eq!(area.city, tmp_area.city);
206        assert_eq!(area.inner, tmp_area.inner);
207    }
208
209    #[test]
210    fn test_object_id() {
211        let area = Area::from_str("334:15:3345:32").unwrap();
212        let private_key = PrivateKey::generate_rsa(1024).unwrap();
213        let people: People = People::new(
214            None,
215            Vec::new(),
216            private_key.public(),
217            Some(area.clone()),
218            None,
219            None,
220        )
221        .build();
222        let people_id = people.desc().calculate_id();
223        let people_data = people.to_vec().unwrap();
224        let new_people = People::clone_from_slice(people_data.as_slice()).unwrap();
225        let new_people_id = new_people.desc().calculate_id();
226        assert_eq!(people_id, new_people_id);
227        let id_info = people_id.info();
228        if let ObjectIdInfo::Standard(obj) = id_info {
229            let tmp_area = obj.area.unwrap();
230            assert_eq!(334, tmp_area.country);
231            assert_eq!(15, tmp_area.carrier);
232            assert_eq!(3345, tmp_area.city);
233            assert_eq!(32, tmp_area.inner);
234            assert_eq!(area.country, tmp_area.country);
235            assert_eq!(area.carrier, tmp_area.carrier);
236            assert_eq!(area.city, tmp_area.city);
237            assert_eq!(area.inner, tmp_area.inner);
238        } else {
239            assert!(false);
240        }
241
242        let area = Area::from_str("3333:10:3345:32");
243        assert!(area.is_err());
244        let area = Area::from_str("333:17:3345:32");
245        assert!(area.is_err());
246        let area = Area::from_str("333:15:8192:32");
247        assert!(area.is_err());
248        let area = Area::from_str("333:15:133345:256");
249        assert!(area.is_err());
250    }
251}