cyfs_base/objects/
chunk.rs

1use crate::*;
2
3use base58::{FromBase58, ToBase58};
4use generic_array::typenum::{marker_traits::Unsigned, U32};
5use generic_array::GenericArray;
6use serde::{Deserialize, Serialize};
7use std::fmt;
8use std::hash::{Hash, Hasher};
9use std::{
10    convert::{Into, TryFrom},
11    str::FromStr,
12};
13
14// unique id in const info
15#[derive(Clone, Eq, PartialEq, Ord, PartialOrd)]
16pub struct ChunkId(GenericArray<u8, U32>);
17
18impl Default for ChunkId {
19    fn default() -> Self {
20        Self(GenericArray::default())
21    }
22}
23
24impl Hash for ChunkId {
25    fn hash<H: Hasher>(&self, state: &mut H) {
26        let mut buff = [0 as u8; 32];
27        let _ = self.raw_encode(buff.as_mut(), &None).unwrap();
28        state.write(buff.as_ref());
29    }
30}
31
32impl std::fmt::Debug for ChunkId {
33    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34        write!(f, "ChunkId: {:?}", self.0.as_slice().to_base58())
35    }
36}
37
38impl std::fmt::Display for ChunkId {
39    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40        write!(f, "{}", self.0.as_slice().to_base58())
41    }
42}
43
44impl FromStr for ChunkId {
45    type Err = BuckyError;
46    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
47        if OBJECT_ID_BASE36_RANGE.contains(&s.len()) {
48            Self::from_base36(s)
49        } else {
50            Self::from_base58(s)
51        }
52    }
53}
54
55impl TryFrom<&ObjectId> for ChunkId {
56    type Error = BuckyError;
57
58    fn try_from(id: &ObjectId) -> Result<Self, Self::Error> {
59        let obj_type_code = id.obj_type_code();
60
61        if obj_type_code == ObjectTypeCode::Chunk {
62            Ok(Self(id.as_ref().clone()))
63        } else {
64            Err(
65                BuckyError::new(
66                    BuckyErrorCode::InvalidParam,
67                    format!("try convert from object id to named object id failed, mismatch obj_type_code, expect obj_type_code is: {}, current obj_type_code is:{}", ObjectTypeCode::Chunk.to_string(), obj_type_code.to_string())
68                )
69            )
70        }
71    }
72}
73
74impl ProtobufTransform<ChunkId> for Vec<u8> {
75    fn transform(value: ChunkId) -> BuckyResult<Self> {
76        Ok(Vec::from(value.0.as_slice()))
77    }
78}
79
80impl ProtobufTransform<&ChunkId> for Vec<u8> {
81    fn transform(value: &ChunkId) -> BuckyResult<Self> {
82        Ok(Vec::from(value.0.as_slice()))
83    }
84}
85
86impl ProtobufTransform<Vec<u8>> for ChunkId {
87    fn transform(value: Vec<u8>) -> BuckyResult<Self> {
88        if value.len() != U32::to_usize() {
89            return Err(BuckyError::new(
90                BuckyErrorCode::InvalidParam,
91                format!(
92                    "try convert from vec<u8> to chunk id failed, invalid len {}",
93                    value.len()
94                ),
95            ));
96        }
97        let mut id = Self::default();
98        unsafe {
99            std::ptr::copy(value.as_ptr(), id.as_mut_slice().as_mut_ptr(), value.len());
100        }
101
102        Ok(id)
103    }
104}
105
106impl From<[u8; 32]> for ChunkId {
107    fn from(v: [u8; 32]) -> Self {
108        Self(GenericArray::from(v))
109    }
110}
111
112impl From<Vec<u8>> for ChunkId {
113    fn from(v: Vec<u8>) -> Self {
114        let ar: [u8; 32] = v.try_into().unwrap_or_else(|v: Vec<u8>| {
115            panic!(
116                "ChunkId expected a Vec of length {} but it was {}",
117                32,
118                v.len()
119            )
120        });
121
122        Self(GenericArray::from(ar))
123    }
124}
125
126impl From<GenericArray<u8, U32>> for ChunkId {
127    fn from(chunk_id: GenericArray<u8, U32>) -> Self {
128        Self(chunk_id)
129    }
130}
131
132impl From<ChunkId> for GenericArray<u8, U32> {
133    fn from(hash: ChunkId) -> Self {
134        hash.0
135    }
136}
137
138impl AsRef<GenericArray<u8, U32>> for ChunkId {
139    fn as_ref(&self) -> &GenericArray<u8, U32> {
140        &self.0
141    }
142}
143
144impl ChunkId {
145    pub fn as_slice(&self) -> &[u8] {
146        self.0.as_slice()
147    }
148
149    pub fn obj_type_code(&self) -> Option<ObjectTypeCode> {
150        Some(ObjectTypeCode::Chunk)
151    }
152
153    pub fn object_id(&self) -> ObjectId {
154        ObjectId::clone_from_slice(self.as_slice()).unwrap()
155    }
156
157    pub fn as_object_id(&self) -> &ObjectId {
158        unsafe { std::mem::transmute::<&ChunkId, &ObjectId>(&self) }
159    }
160
161    fn as_mut_slice(&mut self) -> &mut [u8] {
162        self.0.as_mut_slice()
163    }
164
165    pub fn to_string(&self) -> String {
166        self.0.as_slice().to_base58()
167    }
168
169    pub fn to_base36(&self) -> String {
170        self.0.as_slice().to_base36()
171    }
172
173    pub fn from_base58(s: &str) -> BuckyResult<Self> {
174        let buf = s.from_base58().map_err(|e| {
175            let msg = format!("convert base58 str to chunk id failed, str:{}, {:?}", s, e);
176            error!("{}", msg);
177            BuckyError::new(BuckyErrorCode::ParseError, msg)
178        })?;
179
180        if buf.len() != U32::to_usize() {
181            let msg = format!(
182                "convert base58 str to chunk id failed, str's len not matched:{}, len:{}",
183                s,
184                buf.len()
185            );
186            return Err(BuckyError::new(BuckyErrorCode::ParseError, msg));
187        }
188
189        Ok(Self::from(buf))
190    }
191
192    pub fn from_base36(s: &str) -> BuckyResult<Self> {
193        let buf = s.from_base36().map_err(|e| {
194            let msg = format!("convert base36 str to chunk id failed, str:{}, {:?}", s, e);
195            error!("{}", msg);
196            BuckyError::new(BuckyErrorCode::ParseError, msg)
197        })?;
198
199        if buf.len() != U32::to_usize() {
200            let msg = format!(
201                "convert base36 str to chunk id failed, str's len not matched:{}, len:{}",
202                s,
203                buf.len()
204            );
205            return Err(BuckyError::new(BuckyErrorCode::ParseError, msg));
206        }
207
208        Ok(Self::from(buf))
209    }
210
211    pub async fn calculate(data: &[u8]) -> BuckyResult<Self> {
212        let hash = hash_data(data);
213        Ok(ChunkId::new(&hash, data.len() as u32))
214    }
215
216    pub fn calculate_sync(data: &[u8]) -> BuckyResult<Self> {
217        let hash = hash_data(data);
218        Ok(ChunkId::new(&hash, data.len() as u32))
219    }
220
221    pub fn new(hash_value: &HashValue, len: u32) -> Self {
222        let hash = hash_value.as_slice();
223
224        let mut id = Self::default();
225        let chunkid = id.as_mut_slice();
226        chunkid[0] = 0b_01000000 | (ObjectTypeCode::Chunk.to_u16() as u8) << 4 >> 2;
227        // chunkid[0] = ObjectTypeCode::Chunk.to_u16() as u8;
228        unsafe {
229            *(chunkid[1..5].as_mut_ptr() as *mut u32) = len;
230        }
231        chunkid[5..].copy_from_slice(&hash[0..27]);
232        id
233    }
234
235    pub fn hash(&self) -> &[u8] {
236        let chunkid = self.as_slice();
237        &chunkid[5..]
238    }
239
240    pub fn len(&self) -> usize {
241        let chunkid = self.as_slice();
242        return unsafe { *(chunkid[1..5].as_ptr() as *const u32) } as usize;
243    }
244}
245
246impl RawFixedBytes for ChunkId {
247    fn raw_bytes() -> Option<usize> {
248        Some(U32::to_usize())
249    }
250}
251
252impl RawEncode for ChunkId {
253    fn raw_measure(&self, _purpose: &Option<RawEncodePurpose>) -> Result<usize, BuckyError> {
254        Ok(U32::to_usize())
255    }
256
257    fn raw_encode<'a>(
258        &self,
259        buf: &'a mut [u8],
260        _purpose: &Option<RawEncodePurpose>,
261    ) -> Result<&'a mut [u8], BuckyError> {
262        let bytes = Self::raw_bytes().unwrap();
263        if buf.len() < bytes {
264            let msg = format!(
265                "not enough buffer for encode ChunkId, except={}, got={}",
266                bytes,
267                buf.len()
268            );
269            error!("{}", msg);
270
271            return Err(BuckyError::new(BuckyErrorCode::OutOfLimit, msg));
272        }
273        unsafe {
274            std::ptr::copy(self.0.as_slice().as_ptr(), buf.as_mut_ptr(), bytes);
275        }
276
277        Ok(&mut buf[bytes..])
278    }
279}
280
281impl<'de> RawDecode<'de> for ChunkId {
282    fn raw_decode(buf: &'de [u8]) -> Result<(Self, &'de [u8]), BuckyError> {
283        let bytes = Self::raw_bytes().unwrap();
284        if buf.len() < bytes {
285            let msg = format!(
286                "not enough buffer for decode ChunkId, except={}, got={}",
287                bytes,
288                buf.len()
289            );
290            error!("{}", msg);
291
292            return Err(BuckyError::new(BuckyErrorCode::OutOfLimit, msg));
293        }
294        let mut _id = Self::default();
295        unsafe {
296            std::ptr::copy(buf.as_ptr(), _id.0.as_mut_slice().as_mut_ptr(), bytes);
297        }
298        Ok((_id, &buf[bytes..]))
299    }
300}
301
302use super::raw_diff::{RawDiff, RawPatch};
303
304impl RawDiff for ChunkId {
305    fn diff_measure(&self, right: &Self) -> BuckyResult<usize> {
306        let data = self.as_ref();
307        let r = right.as_ref();
308        data.diff_measure(r)
309    }
310
311    fn diff<'d>(&self, right: &Self, buf: &'d mut [u8]) -> BuckyResult<&'d mut [u8]> {
312        let size = self.diff_measure(right).map_err(|e| {
313            log::error!("ChunkId::diff error:{}", e);
314            e
315        })?;
316        if buf.len() < size {
317            return Err(BuckyError::new(
318                BuckyErrorCode::OutOfLimit,
319                "[raw_diff] not enough buffer for chunk_id",
320            ));
321        }
322
323        self.as_ref().diff(right.as_ref(), buf)
324    }
325}
326
327impl<'de> RawPatch<'de> for ChunkId {
328    fn patch(self, buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> {
329        let data: GenericArray<u8, U32> = self.into();
330        let (data, buf) = data.patch(buf).map_err(|e| {
331            log::error!("ChunkId::patch error:{}", e);
332            e
333        })?;
334        Ok((ChunkId::from(data), buf))
335    }
336}
337
338/// Chunk 存活状态机、
339/// * 默认不存在
340/// * 如果应用层表示感兴趣并且没有在被忽略路由里,则进入New状态
341/// * 如果从关联的DeviceInfo获得或者被动收到广播,则进入Ready状态
342/// * 如果在路由里配置了忽略,则进入Ignore状态
343#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Serialize, Deserialize)]
344pub enum ChunkState {
345    Unknown = 0,
346    NotFound = 1, // 不存在
347    Pending = 2,  // 准备中
348    OnAir = 3,
349    Ready = 4,  // 就绪
350    Ignore = 5, // 被忽略
351}
352
353impl ChunkState {
354    pub fn as_u8(&self) -> u8 {
355        u8::from(self)
356    }
357}
358
359// impl Into<u8> for ChunkState {
360//     fn into(self) -> u8 {
361//         self as u8
362//     }
363// }
364
365impl TryFrom<u8> for ChunkState {
366    type Error = BuckyError;
367
368    fn try_from(value: u8) -> Result<Self, Self::Error> {
369        match value {
370            0 => Ok(ChunkState::Unknown),
371            1 => Ok(ChunkState::NotFound),
372            2 => Ok(ChunkState::Pending),
373            3 => Ok(ChunkState::OnAir),
374            4 => Ok(ChunkState::Ready),
375            5 => Ok(ChunkState::Ignore),
376            _ => {
377                let msg = format!("unknown chunk-state: {}", value);
378                error!("{}", msg);
379                Err(BuckyError::new(BuckyErrorCode::InvalidData, msg))
380            }
381        }
382    }
383}
384
385impl From<ChunkState> for u8 {
386    fn from(value: ChunkState) -> Self {
387        let r = &value;
388        r.into()
389    }
390}
391
392impl From<&ChunkState> for u8 {
393    fn from(value: &ChunkState) -> Self {
394        match value {
395            ChunkState::Unknown => 0,
396            ChunkState::NotFound => 1,
397            ChunkState::Pending => 2,
398            ChunkState::OnAir => 3,
399            ChunkState::Ready => 4,
400            ChunkState::Ignore => 5,
401        }
402    }
403}
404
405// impl From<&ChunkState> for &str {
406//     fn from(value: &ChunkState) -> Self {
407//         match value {
408//             ChunkState::NotFound=>"NotFound",
409//             ChunkState::New=>"New",
410//             ChunkState::Pending=>"Pending",
411//             ChunkState::Ready=>"Ready",
412//             ChunkState::Ignore=>"Ignore",
413//         }
414//     }
415// }
416
417#[cfg(test)]
418mod test {
419    use super::ChunkId;
420    use crate::*;
421
422    use std::convert::TryFrom;
423    use std::str::FromStr;
424    use generic_array::typenum::{marker_traits::Unsigned, U32};
425
426    #[test]
427    fn chunk() {
428        let hash = HashValue::default();
429        let chunk_id = ChunkId::new(&hash, 100);
430        let chunk_id_str = chunk_id.to_string();
431        let chunk_id_str2 = chunk_id.as_object_id().to_string();
432        assert_eq!(chunk_id_str, chunk_id_str2);
433        println!("chunk_id_str:{}", chunk_id_str);
434
435        let chunk_id_from_str = ChunkId::from_str(&chunk_id_str).unwrap();
436        println!("chunk_id_from_str:{:?}", chunk_id_from_str);
437
438        assert_eq!(chunk_id.obj_type_code().unwrap(), ObjectTypeCode::Chunk);
439
440        // 测试chunk_id和object_id的转换
441        let obj_id = chunk_id.object_id();
442        assert_eq!(obj_id.obj_type_code(), ObjectTypeCode::Chunk);
443
444        {
445            let new_chunk_id = ChunkId::try_from(&obj_id).unwrap();
446            assert_eq!(new_chunk_id, chunk_id);
447        }
448
449        assert_eq!(U32::to_usize(), 32);
450    }
451}