use crate::codec::{RawDecode, RawEncode, RawEncodePurpose, RawFixedBytes};
use crate::*;
use std::fmt::{Display, Formatter};
use std::str::FromStr;
#[derive(Eq, PartialEq, Clone, Debug)]
pub struct Area {
pub country: u16,
pub carrier: u8,
pub city: u16,
pub inner: u8, }
impl Area {
pub fn new(country: u16, carrier: u8, city: u16, inner: u8) -> Self {
assert!(country <= 0x1FF);
assert!(city <= 0x1FFF);
assert!(carrier <= 0xF);
Area {
country,
carrier,
city,
inner,
}
}
}
impl FromStr for Area {
type Err = BuckyError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let values = s.split(":");
let mut array: Vec<u16> = vec![];
for value in values {
match value.parse::<u16>() {
Ok(num) => array.push(num),
Err(_) => {
return Err(BuckyError::new(
BuckyErrorCode::InvalidFormat,
"decode area err",
))
}
}
}
if array.len() != 4 {
return Err(BuckyError::new(
BuckyErrorCode::InvalidFormat,
"decode area err",
));
}
if array[0] > 0x1FF || array[2] > 0x1FFF || array[1] > 0xF {
return Err(BuckyError::new(
BuckyErrorCode::InvalidFormat,
"decode area err",
));
}
Ok(Area {
country: array[0],
carrier: array[1] as u8,
city: array[2],
inner: array[3] as u8,
})
}
}
impl Display for Area {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}:{}:{}:{}",
self.country, self.carrier, self.city, self.inner
)
}
}
impl Default for Area {
fn default() -> Self {
Area {
country: 0,
carrier: 0,
city: 0,
inner: 0,
}
}
}
impl RawFixedBytes for Area {
fn raw_bytes() -> Option<usize> {
Some(5)
}
}
impl RawEncode for Area {
fn raw_measure(&self, _purpose: &Option<RawEncodePurpose>) -> Result<usize, BuckyError> {
Ok(5)
}
fn raw_encode<'a>(
&self,
buf: &'a mut [u8],
_purpose: &Option<RawEncodePurpose>,
) -> Result<&'a mut [u8], BuckyError> {
let bytes = Self::raw_bytes().unwrap();
if buf.len() < bytes {
let msg = format!(
"not enough buffer for encode Area, except={}, got={}",
bytes,
buf.len()
);
error!("{}", msg);
return Err(BuckyError::new(BuckyErrorCode::OutOfLimit, msg));
}
buf[0] = self.country as u8;
buf[1] = self.carrier;
buf[2] = (self.city >> 8) as u8 | (self.country >> 8 << 7) as u8;
buf[3] = (self.city << 8 >> 8) as u8;
buf[4] = self.inner;
Ok(&mut buf[5..])
}
}
impl<'de> RawDecode<'de> for Area {
fn raw_decode(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> {
let bytes = Self::raw_bytes().unwrap();
if buf.len() < bytes {
let msg = format!(
"not enough buffer for decode Area, except={}, got={}",
bytes,
buf.len()
);
error!("{}", msg);
return Err(BuckyError::new(BuckyErrorCode::OutOfLimit, msg));
}
let mut area_code = Self::default();
area_code.country = buf[0] as u16 | (buf[2] as u16 >> 7 << 8);
area_code.carrier = buf[1];
area_code.city = ((buf[2] as u16) << 9 >> 1) | (buf[3] as u16);
area_code.inner = buf[4];
Ok((area_code, &buf[5..]))
}
}
#[cfg(test)]
mod test_area {
use crate::*;
use std::str::FromStr;
#[test]
fn test() {
let area = Area::new(333, 14, 3345, 32);
let buf = area.to_vec().unwrap();
let tmp_area = Area::clone_from_slice(buf.as_slice()).unwrap();
assert_eq!(333, tmp_area.country);
assert_eq!(14, tmp_area.carrier);
assert_eq!(3345, tmp_area.city);
assert_eq!(32, tmp_area.inner);
assert_eq!(area.country, tmp_area.country);
assert_eq!(area.carrier, tmp_area.carrier);
assert_eq!(area.city, tmp_area.city);
assert_eq!(area.inner, tmp_area.inner);
let area = Area::new(33, 14, 3345, 32);
let buf = area.to_vec().unwrap();
let tmp_area = Area::clone_from_slice(buf.as_slice()).unwrap();
assert_eq!(33, tmp_area.country);
assert_eq!(14, tmp_area.carrier);
assert_eq!(3345, tmp_area.city);
assert_eq!(32, tmp_area.inner);
assert_eq!(area.country, tmp_area.country);
assert_eq!(area.carrier, tmp_area.carrier);
assert_eq!(area.city, tmp_area.city);
assert_eq!(area.inner, tmp_area.inner);
}
#[test]
fn test_str() {
let area = Area::from_str("333:14:3345:32").unwrap();
let buf = area.to_vec().unwrap();
let tmp_area = Area::clone_from_slice(buf.as_slice()).unwrap();
assert_eq!(333, tmp_area.country);
assert_eq!(14, tmp_area.carrier);
assert_eq!(3345, tmp_area.city);
assert_eq!(32, tmp_area.inner);
assert_eq!(area.country, tmp_area.country);
assert_eq!(area.carrier, tmp_area.carrier);
assert_eq!(area.city, tmp_area.city);
assert_eq!(area.inner, tmp_area.inner);
}
#[test]
fn test_object_id() {
let area = Area::from_str("334:15:3345:32").unwrap();
let private_key = PrivateKey::generate_rsa(1024).unwrap();
let people: People = People::new(
None,
Vec::new(),
private_key.public(),
Some(area.clone()),
None,
None,
)
.build();
let people_id = people.desc().calculate_id();
let people_data = people.to_vec().unwrap();
let new_people = People::clone_from_slice(people_data.as_slice()).unwrap();
let new_people_id = new_people.desc().calculate_id();
assert_eq!(people_id, new_people_id);
let id_info = people_id.info();
if let ObjectIdInfo::Standard(obj) = id_info {
let tmp_area = obj.area.unwrap();
assert_eq!(334, tmp_area.country);
assert_eq!(15, tmp_area.carrier);
assert_eq!(3345, tmp_area.city);
assert_eq!(32, tmp_area.inner);
assert_eq!(area.country, tmp_area.country);
assert_eq!(area.carrier, tmp_area.carrier);
assert_eq!(area.city, tmp_area.city);
assert_eq!(area.inner, tmp_area.inner);
} else {
assert!(false);
}
let area = Area::from_str("3333:10:3345:32");
assert!(area.is_err());
let area = Area::from_str("333:17:3345:32");
assert!(area.is_err());
let area = Area::from_str("333:15:8192:32");
assert!(area.is_err());
let area = Area::from_str("333:15:133345:256");
assert!(area.is_err());
}
}