subspace_core_primitives/
objects.rs

1//! Data structures related to objects (useful data) stored on Subspace Network.
2//!
3//! There are two kinds of mappings:
4//! * for objects within a block
5//! * for global objects in the global history of the blockchain (inside a piece)
6
7use crate::hashes::Blake3Hash;
8use crate::pieces::PieceIndex;
9use core::default::Default;
10use parity_scale_codec::{Decode, Encode};
11use scale_info::prelude::vec;
12use scale_info::prelude::vec::Vec;
13use scale_info::TypeInfo;
14#[cfg(feature = "serde")]
15use serde::{Deserialize, Serialize};
16
17/// Object stored inside of the block
18#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, Encode, Decode, TypeInfo)]
19#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
20#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
21pub struct BlockObject {
22    /// Object hash
23    pub hash: Blake3Hash,
24    /// Offset of object in the encoded block.
25    pub offset: u32,
26}
27
28/// Mapping of objects stored inside of the block
29#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, Encode, Decode, TypeInfo)]
30#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
31#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
32#[cfg_attr(feature = "serde", serde(rename_all_fields = "camelCase"))]
33pub enum BlockObjectMapping {
34    /// V0 of object mapping data structure
35    #[codec(index = 0)]
36    V0 {
37        /// Objects stored inside of the block
38        objects: Vec<BlockObject>,
39    },
40}
41
42impl Default for BlockObjectMapping {
43    fn default() -> Self {
44        Self::V0 {
45            objects: Vec::new(),
46        }
47    }
48}
49
50impl BlockObjectMapping {
51    /// Returns a newly created BlockObjectMapping from a list of object mappings
52    #[inline]
53    pub fn from_objects(objects: impl IntoIterator<Item = BlockObject>) -> Self {
54        Self::V0 {
55            objects: objects.into_iter().collect(),
56        }
57    }
58
59    /// Returns the object mappings
60    pub fn objects(&self) -> &[BlockObject] {
61        match self {
62            Self::V0 { objects, .. } => objects,
63        }
64    }
65
66    /// Returns the object mappings as a mutable slice
67    pub fn objects_mut(&mut self) -> &mut Vec<BlockObject> {
68        match self {
69            Self::V0 { objects, .. } => objects,
70        }
71    }
72}
73
74/// Object stored in the history of the blockchain
75#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, Encode, Decode, TypeInfo)]
76#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
77#[cfg_attr(
78    feature = "serde",
79    serde(from = "CompactGlobalObject", into = "CompactGlobalObject")
80)]
81pub struct GlobalObject {
82    /// Object hash.
83    /// We order by hash, so object hash lookups can be performed efficiently.
84    pub hash: Blake3Hash,
85    /// Piece index where object is contained (at least its beginning, might not fit fully)
86    pub piece_index: PieceIndex,
87    /// Raw record offset of the object in that piece, for use with `Record::to_raw_record_bytes`
88    pub offset: u32,
89}
90
91impl From<CompactGlobalObject> for GlobalObject {
92    fn from(object: CompactGlobalObject) -> Self {
93        Self {
94            hash: object.0,
95            piece_index: object.1,
96            offset: object.2,
97        }
98    }
99}
100
101impl From<GlobalObject> for CompactGlobalObject {
102    fn from(object: GlobalObject) -> Self {
103        Self(object.hash, object.piece_index, object.offset)
104    }
105}
106
107/// Space-saving serialization of an object stored in the history of the blockchain
108#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, Encode, Decode, TypeInfo)]
109#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
110pub struct CompactGlobalObject(Blake3Hash, PieceIndex, u32);
111
112/// Mapping of objects stored in the history of the blockchain
113#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, Encode, Decode, TypeInfo)]
114#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
115#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
116#[cfg_attr(feature = "serde", serde(rename_all_fields = "camelCase"))]
117pub enum GlobalObjectMapping {
118    /// V0 of object mapping data structure.
119    #[codec(index = 0)]
120    V0 {
121        /// Objects stored in the history of the blockchain.
122        objects: Vec<GlobalObject>,
123    },
124}
125
126impl Default for GlobalObjectMapping {
127    fn default() -> Self {
128        Self::V0 {
129            objects: Vec::new(),
130        }
131    }
132}
133
134impl GlobalObjectMapping {
135    /// Returns a newly created GlobalObjectMapping from a list of object mappings
136    #[inline]
137    pub fn from_objects(objects: impl IntoIterator<Item = GlobalObject>) -> Self {
138        Self::V0 {
139            objects: objects.into_iter().collect(),
140        }
141    }
142
143    /// Returns a newly created GlobalObjectMapping from a single object mapping
144    #[inline]
145    pub fn from_object(object: GlobalObject) -> Self {
146        Self::V0 {
147            objects: vec![object],
148        }
149    }
150
151    /// Returns the object mappings
152    pub fn objects(&self) -> &[GlobalObject] {
153        match self {
154            Self::V0 { objects, .. } => objects,
155        }
156    }
157
158    /// Returns the object mappings as a mutable slice
159    pub fn objects_mut(&mut self) -> &mut Vec<GlobalObject> {
160        match self {
161            Self::V0 { objects, .. } => objects,
162        }
163    }
164}