mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Update mapping types.
This commit is contained in:
parent
197875c97a
commit
c85103816c
@ -5,16 +5,17 @@ Mapping Types
|
|||||||
=============
|
=============
|
||||||
|
|
||||||
Mapping types use the syntax ``mapping(_KeyType => _ValueType)`` and variables
|
Mapping types use the syntax ``mapping(_KeyType => _ValueType)`` and variables
|
||||||
are declared as a mapping type using the syntax ``mapping (_KeyType => _ValueType) _VariableModifiers _VariableName``.
|
of mapping type are declared using the syntax ``mapping(_KeyType => _ValueType) _VariableName``.
|
||||||
The ``_KeyType`` can be any elementary type. This means it can be any of
|
The ``_KeyType`` can be any
|
||||||
the built-in value types plus ``bytes`` and ``string``. User-defined
|
built-in value type plus ``bytes`` and ``string``. User-defined
|
||||||
or complex types like contract types, enums, mappings, structs and any array type
|
or complex types such as contract types, enums, mappings, structs or array types
|
||||||
apart from ``bytes`` and ``string`` are not allowed.
|
apart from ``bytes`` and ``string`` are not allowed.
|
||||||
``_ValueType`` can be any type, including mappings.
|
``_ValueType`` can be any type, including mappings, arrays and structs.
|
||||||
|
|
||||||
You can think of mappings as `hash tables <https://en.wikipedia.org/wiki/Hash_table>`_, which are virtually initialised
|
You can think of mappings as `hash tables <https://en.wikipedia.org/wiki/Hash_table>`_, which are virtually initialised
|
||||||
such that every possible key exists and is mapped to a value whose
|
such that every possible key exists and is mapped to a value whose
|
||||||
byte-representation is all zeros, a type's :ref:`default value <default-value>`. The similarity ends there, the key data is not stored in a
|
byte-representation is all zeros, a type's :ref:`default value <default-value>`.
|
||||||
|
The similarity ends there, the key data is not stored in a
|
||||||
mapping, only its ``keccak256`` hash is used to look up the value.
|
mapping, only its ``keccak256`` hash is used to look up the value.
|
||||||
|
|
||||||
Because of this, mappings do not have a length or a concept of a key or
|
Because of this, mappings do not have a length or a concept of a key or
|
||||||
@ -59,7 +60,8 @@ contract that returns the value at the specified address.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
The example below is a simplified version of an `ERC20 token <https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol>`_.
|
The example below is a simplified version of an
|
||||||
|
`ERC20 token <https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol>`_.
|
||||||
``_allowances`` is an example of a mapping type inside another mapping type.
|
``_allowances`` is an example of a mapping type inside another mapping type.
|
||||||
The example below uses ``_allowances`` to record the amount someone else is allowed to withdraw from your account.
|
The example below uses ``_allowances`` to record the amount someone else is allowed to withdraw from your account.
|
||||||
|
|
||||||
@ -111,16 +113,18 @@ The example below uses ``_allowances`` to record the amount someone else is allo
|
|||||||
Iterable Mappings
|
Iterable Mappings
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
Mappings are not iterable, but it is possible to implement a data structure on
|
You cannot iterate over mappings, i.e. you cannot enumerate their keys.
|
||||||
|
It is possible, though, to implement a data structure on
|
||||||
top of them and iterate over that. For example, the code below implements an
|
top of them and iterate over that. For example, the code below implements an
|
||||||
``IterableMapping`` library that the ``User`` contract then adds data too, and
|
``IterableMapping`` library that the ``User`` contract then adds data too, and
|
||||||
the ``sum`` function iterates over to sum all the values.
|
the ``sum`` function iterates over to sum all the values.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
pragma solidity >=0.4.0 <0.7.0;
|
pragma solidity >=0.5.99 <0.7.0;
|
||||||
|
|
||||||
library IterableMapping {
|
struct IndexValue { uint keyIndex; uint value; }
|
||||||
|
struct KeyFlag { uint key; bool deleted; }
|
||||||
|
|
||||||
struct itmap {
|
struct itmap {
|
||||||
mapping(uint => IndexValue) data;
|
mapping(uint => IndexValue) data;
|
||||||
@ -128,9 +132,7 @@ the ``sum`` function iterates over to sum all the values.
|
|||||||
uint size;
|
uint size;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct IndexValue { uint keyIndex; uint value; }
|
library IterableMapping {
|
||||||
struct KeyFlag { uint key; bool deleted; }
|
|
||||||
|
|
||||||
function insert(itmap storage self, uint key, uint value) internal returns (bool replaced) {
|
function insert(itmap storage self, uint key, uint value) internal returns (bool replaced) {
|
||||||
uint keyIndex = self.data[key].keyIndex;
|
uint keyIndex = self.data[key].keyIndex;
|
||||||
self.data[key].value = value;
|
self.data[key].value = value;
|
||||||
@ -183,22 +185,27 @@ the ``sum`` function iterates over to sum all the values.
|
|||||||
// How to use it
|
// How to use it
|
||||||
contract User {
|
contract User {
|
||||||
// Just a struct holding our data.
|
// Just a struct holding our data.
|
||||||
IterableMapping.itmap data;
|
itmap data;
|
||||||
|
// Apply library functions to the data type.
|
||||||
|
using IterableMapping for itmap;
|
||||||
|
|
||||||
// Insert something
|
// Insert something
|
||||||
function insert(uint k, uint v) public returns (uint size) {
|
function insert(uint k, uint v) public returns (uint size) {
|
||||||
// Actually calls itmap_impl.insert, auto-supplying the first parameter for us.
|
// This calls IterableMapping.insert(data, k, v)
|
||||||
IterableMapping.insert(data, k, v);
|
data.insert(k, v);
|
||||||
// We can still access members of the struct - but we should take care not to mess with them.
|
// We can still access members of the struct,
|
||||||
|
// but we should take care not to mess with them.
|
||||||
return data.size;
|
return data.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Computes the sum of all stored data.
|
// Computes the sum of all stored data.
|
||||||
function sum() public view returns (uint s) {
|
function sum() public view returns (uint s) {
|
||||||
for (uint i = IterableMapping.iterate_start(data);
|
for (
|
||||||
IterableMapping.iterate_valid(data, i);
|
uint i = data.iterate_start();
|
||||||
i = IterableMapping.iterate_next(data, i)) {
|
data.iterate_valid(i);
|
||||||
(, uint value) = IterableMapping.iterate_get(data, i);
|
i = data.iterate_next(i)
|
||||||
|
) {
|
||||||
|
(, uint value) = data.iterate_get(i);
|
||||||
s += value;
|
s += value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user