difftreelog
refactor account for key sizes in Properties
in: master
1 file changed
primitives/data-structs/src/lib.rsdiffbeforeafterboth1104}1104}110511051106impl PropertyScope {1106impl PropertyScope {1107 pub fn prefix(&self) -> &'static [u8] {1108 match self {1109 Self::None => b"",1110 Self::Rmrk => b"rmrk:",1111 }1112 }1107 /// Apply scope to property key.1113 /// Apply scope to property key.1108 pub fn apply(self, key: PropertyKey) -> Result<PropertyKey, PropertiesError> {1114 pub fn apply(self, key: PropertyKey) -> Result<PropertyKey, PropertiesError> {1109 let scope_str: &[u8] = match self {1115 let prefix = self.prefix();1116 if prefix == b"" {1110 Self::None => return Ok(key),1117 return Ok(key);1111 Self::Rmrk => b"rmrk",1112 };1118 }11131114 [scope_str, b":", key.as_slice()]1119 [prefix, key.as_slice()]1115 .concat()1120 .concat()1116 .try_into()1121 .try_into()1117 .map_err(|_| PropertiesError::PropertyKeyIsTooLong)1122 .map_err(|_| PropertiesError::PropertyKeyIsTooLong)1197 self.0.contains_key(key)1202 self.0.contains_key(key)1198 }1203 }11991200 fn metadata_encoded_len() -> usize {1201 // Max length of key length + max length of value length for max properties1202 // + max length of table size length1203 (4 * 4) * (MAX_PROPERTIES_PER_ITEM as usize) + 41204 }120512041206 /// Check if map contains key with key validation.1205 /// Check if map contains key with key validation.1207 fn check_property_key(key: &PropertyKey) -> Result<(), PropertiesError> {1206 fn check_property_key(key: &PropertyKey) -> Result<(), PropertiesError> {1224 self.0.values()1223 self.0.values()1225 }1224 }12251226 pub fn iter(&self) -> impl Iterator<Item = (&PropertyKey, &Value)> {1227 self.0.iter()1228 }1226}1229}122712301228impl<Value> IntoIterator for PropertiesMap<Value> {1231impl<Value> IntoIterator for PropertiesMap<Value> {1261/// Alias for property permissions map.1264/// Alias for property permissions map.1262pub type PropertiesPermissionMap = PropertiesMap<PropertyPermission>;1265pub type PropertiesPermissionMap = PropertiesMap<PropertyPermission>;12661267fn slice_size(data: &[u8]) -> u32 {1268 scoped_slice_size(PropertyScope::None, data)1269}1270fn scoped_slice_size(scope: PropertyScope, data: &[u8]) -> u32 {1271 use codec::Compact;1272 let prefix = scope.prefix();1273 <Compact<u32>>::encoded_size(&Compact(data.len() as u32 + prefix.len() as u32)) as u321274 + data.len() as u321275 + prefix.len() as u321276}126312771264/// Wrapper for properties map with consumed space control.1278/// Wrapper for properties map with consumed space control.1265#[derive(Encode, Decode, TypeInfo, Clone, PartialEq)]1279#[derive(Encode, Decode, TypeInfo, Clone, PartialEq)]1266pub struct Properties<const S: u32> {1280pub struct Properties<const S: u32> {1267 map: PropertiesMap<PropertyValue>,1281 map: PropertiesMap<PropertyValue>,1268 consumed_space: u32,1282 consumed_space: u32,1283 // May be not zero, previously served as a current S generic1269 space_limit: u32,1284 _reserved: u32,1270}1285}127112861272impl<const S: u32> MaxEncodedLen for Properties<S> {1287impl<const S: u32> MaxEncodedLen for Properties<S> {1273 fn max_encoded_len() -> usize {1288 fn max_encoded_len() -> usize {1274 <PropertiesMap<PropertyValue>>::metadata_encoded_len()1289 // len of map + len of consumed_space + len of space_limit1275 + (u32::max_encoded_len() * 2)1290 u32::max_encoded_len() * 3 + S as usize1276 + S as usize1277 }1291 }1278}1292}1289 Self {1303 Self {1290 map: PropertiesMap::new(),1304 map: PropertiesMap::new(),1291 consumed_space: 0,1305 consumed_space: 0,1292 space_limit: u32::MAX,1306 _reserved: 0,1293 }1307 }1294 }1308 }129513091298 let value = self.map.remove(key)?;1312 let value = self.map.remove(key)?;129913131300 if let Some(ref value) = value {1314 if let Some(ref value) = value {1301 let value_len = value.len() as u32;1315 let kv_len = slice_size(key) + slice_size(value);1302 self.consumed_space -= value_len;1316 self.consumed_space = self.consumed_space.saturating_sub(kv_len);1303 }1317 }130413181305 Ok(value)1319 Ok(value)1313 /// Recomputes the consumed space for the current properties state.1327 /// Recomputes the consumed space for the current properties state.1314 /// Needed to repair a token due to a bug fixed in the [PR #733](https://github.com/UniqueNetwork/unique-chain/pull/773).1328 /// Needed to repair a token due to a bug fixed in the [PR #733](https://github.com/UniqueNetwork/unique-chain/pull/773).1315 pub fn recompute_consumed_space(&mut self) {1329 pub fn recompute_consumed_space(&mut self) {1316 self.consumed_space = self.map.values().map(|value| value.len() as u32).sum();1330 self.consumed_space = self1331 .map1332 .iter()1333 .map(|(key, value)| slice_size(key) + slice_size(value))1334 .sum();1317 }1335 }1318}1336}1335 key: PropertyKey,1353 key: PropertyKey,1336 value: Self::Value,1354 value: Self::Value,1337 ) -> Result<Option<Self::Value>, PropertiesError> {1355 ) -> Result<Option<Self::Value>, PropertiesError> {1356 let key_size = scoped_slice_size(scope, &key);1338 let value_len = value.len();1357 let value_size = slice_size(&value) as u32;133913581340 if self.consumed_space as usize + value_len > self.space_limit.min(S) as usize1359 if self.consumed_space + value_size + key_size > S && !cfg!(feature = "runtime-benchmarks")1341 && !cfg!(feature = "runtime-benchmarks")1342 {1360 {1343 return Err(PropertiesError::NoSpaceForProperty);1361 return Err(PropertiesError::NoSpaceForProperty);1344 }1362 }134513631346 let value_len = value_len as u32;1347 let old_value = self.map.try_scoped_set(scope, key, value)?;1364 let old_value = self.map.try_scoped_set(scope, key, value)?;134813651349 let old_value_len = old_value.as_ref().map(|v| v.len() as u32).unwrap_or(0);1366 if let Some(old_value) = old_value.as_ref() {13501367 let old_value_size = slice_size(&old_value);1351 if value_len > old_value_len {1352 self.consumed_space += value_len - old_value_len;1368 self.consumed_space = self.consumed_space.saturating_sub(old_value_size) + value_size;1353 } else {1369 } else {1354 self.consumed_space -= old_value_len - value_len;1370 self.consumed_space += key_size + value_size;1355 }1371 }135613721357 Ok(old_value)1373 Ok(old_value)