/
LibraryMappingString.sol
182 lines (172 loc) · 8.24 KB
/
LibraryMappingString.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
// SPDX-License-Identifier: AGPL-3.0
pragma solidity 0.8.7;
/// @title Organizes methods that may be attached to `mapping(string => string)` type
/// @notice **Warning** any value of `""` is treated as _null_ or _undefined_
/// @author S0AndS0
library LibraryMappingString {
/// @notice Retrieves stored value `string` or throws an error if _undefined_
/// @dev Passes parameters to `getOrError` with default Error `_reason` to throw
/// @param _self **{mapping(string => string)}** Mapping of key/value `string` pairs
/// @param _key **{string}** Mapping key `string` to lookup corresponding value `string` for
/// @return **{string}** Value for given key `string`
/// @custom:throws **{Error}** `"LibraryMappingString.get: value not defined"`
function get(mapping(string => string) storage _self, string calldata _key)
external
view
returns (string memory)
{
return
getOrError(
_self,
_key,
"LibraryMappingString.get: value not defined"
);
}
/// @notice Retrieves stored value `string` or provided default `string` if _undefined_
/// @param _self **{mapping(string => string)}** Mapping of key/value `string` pairs
/// @param _key **{string}** Mapping key `string` to lookup corresponding value `string` for
/// @param _default **{string}** Value to return if key `string` lookup is _undefined_
/// @return **{string}** Value `string` for given key `string` or `_default` if _undefined_
function getOrElse(
mapping(string => string) storage _self,
string calldata _key,
string memory _default
) external view returns (string memory) {
string memory _value = _self[_key];
return
keccak256(bytes(_value)) != keccak256(bytes(""))
? _value
: _default;
}
/// @notice Allows for defining custom error reason if value `string` is _undefined_
/// @param _self **{mapping(string => string)}** Mapping of key/value `string` pairs
/// @param _key **{string}** Mapping key `string` to lookup corresponding value `string` for
/// @param _reason **{string}** Custom error message to throw if value `string` is _undefined_
/// @return **{string}** Value for given key `string`
/// @custom:throws **{Error}** _reason if value is _undefined_
function getOrError(
mapping(string => string) storage _self,
string calldata _key,
string memory _reason
) public view returns (string memory) {
string memory _value = _self[_key];
require(keccak256(bytes(_value)) != keccak256(bytes("")), _reason);
return _value;
}
/// @notice Check if `string` key has a corresponding value `string` defined
/// @param _self **{mapping(string => string)}** Mapping of key/value `string` pairs
/// @param _key **{string}** Mapping key to check if value `string` is defined
/// @return **{bool}** true if value `string` is defined, or `false` if _undefined_
function has(mapping(string => string) storage _self, string calldata _key)
external
view
returns (bool)
{
return keccak256(bytes(_self[_key])) != keccak256(bytes(""));
}
/// @notice Store `_value` under given `_key` **without** preventing unintentional overwrites
/// @dev Passes parameters to `overwriteOrError` with default Error `_reason` to throw
/// @param _self **{mapping(string => string)}** Mapping of key/value `string` pairs
/// @param _key **{string}** Mapping key to set corresponding value `string` for
/// @param _value **{string}** Mapping value to set
/// @custom:throws **{Error}** `"LibraryMappingString.overwrite: value cannot be """`
function overwrite(
mapping(string => string) storage _self,
string calldata _key,
string calldata _value
) external {
overwriteOrError(
_self,
_key,
_value,
'LibraryMappingString.overwrite: value cannot be ""'
);
}
/// @notice Store `_value` under given `_key` **without** preventing unintentional overwrites
/// @param _self **{mapping(string => string)}** Mapping of key/value `string` pairs
/// @param _key **{string}** Mapping key to set corresponding value `string` for
/// @param _value **{string}** Mapping value to set
/// @param _reason **{string}** Custom error message to present if value `string` is `""`
/// @custom:throws **{Error}** `_reason` if value is `""`
function overwriteOrError(
mapping(string => string) storage _self,
string calldata _key,
string calldata _value,
string memory _reason
) public {
require(keccak256(bytes(_value)) != keccak256(bytes("")), _reason);
_self[_key] = _value;
}
/// @notice Delete value `string` for given `_key`
/// @dev Passes parameters to `removeOrError` with default Error `_reason` to throw
/// @param _self **{mapping(string => string)}** Mapping of key/value `string` pairs
/// @param _key **{string}** Mapping key to delete corresponding value `string` for
/// @return **{string}** Stored value `string` for given key `string`
/// @custom:throws **{Error}** `"LibraryMappingString.remove: value not defined"`
function remove(
mapping(string => string) storage _self,
string calldata _key
) external returns (string memory) {
return
removeOrError(
_self,
_key,
"LibraryMappingString.remove: value not defined"
);
}
/// @notice Delete value `string` for given `_key`
/// @param _self **{mapping(string => string)}** Mapping of key/value `string` pairs
/// @param _key **{string}** Mapping key to delete corresponding value `string` for
/// @param _reason **{string}** Custom error message to throw if value `string` is _undefined_
/// @return **{string}** Stored value `string` for given key `string`
/// @custom:throws **{Error}** _reason if value is _undefined_
function removeOrError(
mapping(string => string) storage _self,
string calldata _key,
string memory _reason
) public returns (string memory) {
string memory _value = _self[_key];
require(keccak256(bytes(_value)) != keccak256(bytes("")), _reason);
delete _self[_key];
return _value;
}
/// @notice Store `_value` under given `_key` while preventing unintentional overwrites
/// @dev Passes parameters to `setOrError` with default Error `_reason` to throw
/// @param _self **{mapping(string => string)}** Mapping of key/value `string` pairs
/// @param _key **{string}** Mapping key to set corresponding value `string` for
/// @param _value **{string}** Mapping value to set
/// @custom:throws **{Error}** `"LibraryMappingString.set: value already defined"`
/// @custom:throws **{Error}** `"LibraryMappingString.setOrError: value cannot be """`
function set(
mapping(string => string) storage _self,
string calldata _key,
string calldata _value
) external {
setOrError(
_self,
_key,
_value,
"LibraryMappingString.set: value already defined"
);
}
/// @notice Store `_value` under given `_key` while preventing unintentional overwrites
/// @param _self **{mapping(string => string)}** Mapping of key/value `string` pairs
/// @param _key **{string}** Mapping key to set corresponding value `string` for
/// @param _value **{string}** Mapping value to set
/// @param _reason **{string}** Custom error message to present if value `string` is defined
/// @custom:throws **{Error}** _reason if value is defined
/// @custom:throws **{Error}** `"LibraryMappingString.setOrError: value cannot be """`
function setOrError(
mapping(string => string) storage _self,
string calldata _key,
string calldata _value,
string memory _reason
) public {
require(keccak256(bytes(_self[_key])) == keccak256(bytes("")), _reason);
require(
keccak256(bytes(_value)) != keccak256(bytes("")),
'LibraryMappingString.setOrError: value cannot be ""'
);
_self[_key] = _value;
}
}