cyfs_base/objects/
unique_id.rs1use crate::*;
2
3use generic_array::typenum::{marker_traits::Unsigned, U16};
4use generic_array::GenericArray;
5use std::fmt;
6use base58::ToBase58;
7
8#[derive(Clone, Eq, PartialEq)]
10pub struct UniqueId(GenericArray<u8, U16>);
11
12impl std::fmt::Debug for UniqueId {
13 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14 write!(f, "UniqueId: {}", self.0.as_slice().to_base58())
15 }
16}
17
18impl std::fmt::Display for UniqueId {
19 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20 write!(f, "{}", self.0.as_slice().to_base58())
21 }
22}
23
24impl From<GenericArray<u8, U16>> for UniqueId {
25 fn from(hash: GenericArray<u8, U16>) -> Self {
26 Self(hash)
27 }
28}
29
30impl From<UniqueId> for GenericArray<u8, U16> {
31 fn from(hash: UniqueId) -> Self {
32 hash.0
33 }
34}
35
36impl AsRef<GenericArray<u8, U16>> for UniqueId {
37 fn as_ref(&self) -> &GenericArray<u8, U16> {
38 &self.0
39 }
40}
41
42impl Default for UniqueId {
43 fn default() -> Self {
44 Self(GenericArray::default())
45 }
46}
47
48impl UniqueId {
49 pub fn as_slice(&self) -> &[u8] {
50 self.0.as_slice()
51 }
52
53 pub fn as_mut_slice(&mut self) -> &mut [u8] {
54 self.0.as_mut_slice()
55 }
56
57 pub fn clone_from_slice(slice: &[u8]) -> Self {
58 UniqueId(GenericArray::clone_from_slice(slice))
59 }
60
61 pub fn create(slice: &[u8]) -> Self {
62 let mut unique_slice = [0u8; 16];
63 let mut count = 0;
64 for c in slice {
65 unique_slice[count] = *c;
66 count += 1;
67 if count >= 16 {
68 break;
69 }
70 }
71
72 UniqueId::clone_from_slice(&unique_slice)
73 }
74
75 pub fn create_with_hash(src: &[u8]) -> Self {
77 use sha2::Digest;
78
79 let mut sha256 = sha2::Sha256::new();
80 sha256.input(src);
81 Self::create(&sha256.result())
82 }
83}
84
85impl RawFixedBytes for UniqueId {
86 fn raw_bytes() -> Option<usize> {
87 Some(U16::to_usize())
88 }
89}
90
91impl RawEncode for UniqueId {
92 fn raw_measure(&self, _purpose: &Option<RawEncodePurpose>) -> Result<usize, BuckyError> {
93 Ok(U16::to_usize())
94 }
95
96 fn raw_encode<'a>(
97 &self,
98 buf: &'a mut [u8],
99 _purpose: &Option<RawEncodePurpose>,
100 ) -> Result<&'a mut [u8], BuckyError> {
101 let bytes = Self::raw_bytes().unwrap();
102 if buf.len() < bytes {
103 let msg = format!(
104 "not enough buffer for encode UniqueId, except={}, got={}",
105 bytes,
106 buf.len()
107 );
108 error!("{}", msg);
109
110 return Err(BuckyError::new(BuckyErrorCode::OutOfLimit, msg));
111 }
112 unsafe {
113 std::ptr::copy(self.0.as_slice().as_ptr(), buf.as_mut_ptr(), bytes);
114 }
115
116 Ok(&mut buf[bytes..])
117 }
118}
119
120impl<'de> RawDecode<'de> for UniqueId {
121 fn raw_decode(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> {
122 let bytes = Self::raw_bytes().unwrap();
123 if buf.len() < bytes {
124 let msg = format!(
125 "not enough buffer for decode UniqueId, except={}, got={}",
126 bytes,
127 buf.len()
128 );
129 error!("{}", msg);
130
131 return Err(BuckyError::new(BuckyErrorCode::OutOfLimit, msg));
132 }
133 let mut _id = Self::default();
134 unsafe {
135 std::ptr::copy(buf.as_ptr(), _id.0.as_mut_slice().as_mut_ptr(), bytes);
136 }
137 Ok((_id, &buf[bytes..]))
138 }
139}
140
141impl ProtobufTransform<&UniqueId> for Vec<u8> {
142 fn transform(value: &UniqueId) -> BuckyResult<Self> {
143 Ok(Vec::from(value.0.as_slice()))
144 }
145}
146
147impl ProtobufTransform<Vec<u8>> for UniqueId {
148 fn transform(value: Vec<u8>) -> BuckyResult<Self> {
149 if value.len() != 32 {
150 return Err(BuckyError::new(
151 BuckyErrorCode::InvalidParam,
152 format!(
153 "try convert from vec<u8> to named unique id failed, invalid len {}",
154 value.len()
155 ),
156 ));
157 }
158 let mut id = Self::default();
159 unsafe {
160 std::ptr::copy(value.as_ptr(), id.as_mut_slice().as_mut_ptr(), value.len());
161 }
162
163 Ok(id)
164 }
165}
166
167#[cfg(test)]
168mod test {
169 use crate::*;
170
171 #[test]
172 fn test_codec() {
173 let id = UniqueId::default();
174 let len = id.raw_measure(&None).unwrap();
175 assert_eq!(len, 16);
176 let buf = id.to_vec().unwrap();
177 let (id2, left) = UniqueId::raw_decode(&buf).unwrap();
178 assert_eq!(id, id2);
179 assert!(left.is_empty());
180
181 let hash = id.raw_hash_value().unwrap();
182 println!("hash: {}", hash);
183 }
184}