Skip to content

Commit 19883e2

Browse files
committed
Initial commit
0 parents  commit 19883e2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+5492
-0
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
build
2+
.vscode
3+
.idea
4+
cmake-build-*/

CMakeLists.txt

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#
2+
# Copyright Soramitsu Co., Ltd. All Rights Reserved.
3+
# SPDX-License-Identifier: Apache-2.0
4+
#
5+
6+
cmake_minimum_required(VERSION 3.12)
7+
8+
include(${CMAKE_CURRENT_LIST_DIR}/cmake/HunterGate.cmake)
9+
10+
HunterGate(
11+
URL https://github.com/soramitsu/soramitsu-hunter/archive/master.tar.gz
12+
SHA1 39113c56b1d6be190b13995348816710dc1715f7
13+
)
14+
15+
project(Scale CXX)
16+
17+
set(CMAKE_CXX_STANDARD 17)
18+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
19+
set(CMAKE_CXX_EXTENSIONS OFF)
20+
21+
option(BUILD_TESTS "Whether to include the test suite in build" OFF)
22+
23+
hunter_add_package(Boost)
24+
find_package(Boost CONFIG REQUIRED)
25+
26+
hunter_add_package(Microsoft.GSL)
27+
find_package(Microsoft.GSL CONFIG REQUIRED)
28+
29+
add_subdirectory(src)
30+
31+
if (${BUILD_TESTS})
32+
add_subdirectory(test ${CMAKE_BINARY_DIR}/tests_bin)
33+
endif()
34+
35+
###############################################################################
36+
# INSTALLATION
37+
###############################################################################
38+
39+
include(GNUInstallDirs)
40+
41+
install(TARGETS scale buffer EXPORT scaleConfig
42+
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
43+
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
44+
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
45+
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
46+
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
47+
FRAMEWORK DESTINATION ${CMAKE_INSTALL_PREFIX}
48+
)
49+
50+
install(
51+
DIRECTORY ${CMAKE_SOURCE_DIR}/include/scale
52+
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
53+
)
54+
55+
install(
56+
EXPORT scaleConfig
57+
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/scale
58+
NAMESPACE scale::
59+
)

README.md

+154
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
# SCALE codec C++ implementation
2+
fully meets polkadot specification.\
3+
It allows encoding and decoding following data types:
4+
* Built-in integer types specified by size:
5+
* ```uint8_t```, ```int8_t```
6+
* ```uint16_t```, ```int16_t```
7+
* ```uint32_t```, ```int32_t```
8+
* ```uint64_t```, ```int64_t```
9+
* bool values
10+
* pairs of types represented by ```std::pair<T1, T2>```
11+
* compact integers represented by CompactInteger type
12+
* optional values represented by ```boost::optional<T>```
13+
* as special case of optional values ```boost::optional<bool>``` is encoded using one byte following specification.
14+
* collections of items represented by ```std::vector<T>```
15+
* variants represented by ```boost::variant<T...>```
16+
17+
## ScaleEncoderStream
18+
class ScaleEncoderStream is in charge of encoding data
19+
20+
```c++
21+
ScaleEncoderStream s;
22+
uint32_t ui32 = 123u;
23+
uint8_t ui8 = 234u;
24+
std::string str = "asdasdasd";
25+
auto * raw_str = "zxczxczx";
26+
bool b = true;
27+
CompactInteger ci = 123456789;
28+
boost::variant<uint8_t, uint32_t, CompactInteger> vint = CompactInteger(12345);
29+
boost::optional<std::string> opt_str = "asdfghjkl";
30+
boost::optional<bool> opt_bool = false;
31+
std::pair<uint8_t, uint32_t> pair{1u, 2u};
32+
std::vector<uint32_t> coll_ui32 = {1u, 2u, 3u, 4u};
33+
std::vector<std::string> coll_str = {"asd", "fgh", "jkl"};
34+
std::vector<std::vector<int32_t>> coll_coll_i32 = {{1, 2, 3}, {4, 5, 6, 7}};
35+
try {
36+
s << ui32 << ui8 << str << raw_str << b << ci << vint;
37+
s << opt_str << opt_bool << pair << coll_ui32 << coll_str << coll_coll_i32;
38+
} catch (std::runtime_error &e) {
39+
// handle error
40+
// for example make and return outcome::result
41+
return outcome::failure(e.code());
42+
}
43+
```
44+
You can now get encoded data:
45+
```c++
46+
ByteArray data = s.data();
47+
```
48+
49+
## ScaleDecoderStream
50+
class ScaleEncoderStream is in charge of encoding data
51+
52+
```c++
53+
ByteArray bytes = {...};
54+
ScaleEncoderStream s(bytes);
55+
uint32_t ui32 = 0u;
56+
uint8_t ui8 = 0u;
57+
std::string str;
58+
bool b = true;
59+
CompactInteger ci;
60+
boost::variant<uint8_t, uint32_t, CompactInteger> vint;
61+
boost::optional<std::string> opt_str;
62+
boost::optional<bool> opt_bool;
63+
std::pair<uint8_t, uint32_t> pair{};
64+
std::vector<uint32_t> coll_ui32;
65+
std::vector<std::string> coll_str;
66+
std::vector<std::vector<int32_t>> coll_coll_i32;
67+
try {
68+
s >> ui32 >> ui8 >> str >> b >> ci >> vint;
69+
s >> opt_str >> opt_bool >> pair >> coll_ui32 >> coll_str >> coll_coll_i32;
70+
} catch (std::system_error &e) {
71+
// handle error
72+
}
73+
```
74+
75+
## Custom types
76+
You may need to encode or decode custom data types, you have to define custom << and >> operators.
77+
Please note, that your custom data types must be default-constructible.
78+
```c++
79+
struct MyType {
80+
int a = 0;
81+
std::string b;
82+
};
83+
84+
ScaleEncoderStream &operator<<(ScaleEncoderStream &s, const MyType &v) {
85+
return s << v.a << v.b;
86+
}
87+
88+
ScaleDecoderStream &operator>>(ScaleDecoderStream &s, MyType &v) {
89+
return s >> v.a >> v.b;
90+
}
91+
```
92+
Now you can use them in collections, optionals and variants
93+
```c++
94+
std::vector<MyType> v = {{1, "asd"}, {2, "qwe"}};
95+
ScaleEncoderStream s;
96+
try {
97+
s << v;
98+
} catch (...) {
99+
// handle error
100+
}
101+
```
102+
The same for ```ScaleDecoderStream```
103+
```c++
104+
ByteArray data = {...};
105+
std::vector<MyType> v;
106+
ScaleDecoderStream s{data};
107+
try {
108+
s >> v;
109+
} catch (...) {
110+
// handle error
111+
}
112+
```
113+
114+
## Convenience functions
115+
Convenience functions
116+
```c++
117+
template<class T>
118+
outcome::result<std::vector<uint8_t>> encode(T &&t);
119+
120+
template <class T>
121+
outcome::result<T> decode(gsl::span<const uint8_t> span)
122+
123+
template <class T>
124+
outcome::result<T> decode(ScaleDecoderStream &s)
125+
```
126+
are wrappers over ```<<``` and ```>>``` operators described above.
127+
128+
Encoding data using ```encode``` convenience function looks as follows:
129+
```c++
130+
std::vector<uint32_t> v = {1u, 2u, 3u, 4u};
131+
auto &&result = encode(v);
132+
if (!res) {
133+
// handle error
134+
}
135+
```
136+
137+
Decoding data using ```decode``` convenience function looks as follows:
138+
139+
```c++
140+
ByteArray bytes = {...};
141+
outcome::result<MyType> result = decode<MyType>(bytes);
142+
if (!result) {
143+
// handle error
144+
}
145+
```
146+
or
147+
```c++
148+
ByteArray bytes = {...};
149+
ScaleDecoderStream s(bytes);
150+
outcome::result<MyType> result = decode<MyType>(s);
151+
if (!result) {
152+
// handle error
153+
}
154+
```

0 commit comments

Comments
 (0)