amulet-core 2.0a5__cp312-cp312-win_amd64.whl → 2.0a6__cp312-cp312-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of amulet-core might be problematic. Click here for more details.
- amulet/__init__.cp312-win_amd64.pyd +0 -0
- amulet/__init__.py.cpp +39 -0
- amulet/_version.py +3 -3
- amulet/biome.py.cpp +122 -0
- amulet/block.py.cpp +377 -0
- amulet/block_entity.py.cpp +115 -0
- amulet/chunk.py.cpp +80 -0
- amulet/chunk_components/biome_3d_component.cpp +5 -0
- amulet/chunk_components/biome_3d_component.hpp +79 -0
- amulet/chunk_components/block_component.cpp +41 -0
- amulet/chunk_components/block_component.hpp +88 -0
- amulet/chunk_components/block_entity_component.cpp +5 -0
- amulet/chunk_components/block_entity_component.hpp +147 -0
- amulet/chunk_components/section_array_map.cpp +129 -0
- amulet/chunk_components/section_array_map.hpp +147 -0
- amulet/collections/eq.py.hpp +37 -0
- amulet/collections/hash.py.hpp +27 -0
- amulet/collections/holder.py.hpp +37 -0
- amulet/collections/iterator.py.hpp +80 -0
- amulet/collections/mapping.py.hpp +192 -0
- amulet/collections/mutable_mapping.py.hpp +215 -0
- amulet/collections/sequence.py.hpp +164 -0
- amulet/img/missing_world_icon.png +0 -0
- amulet/io/binary_reader.hpp +45 -0
- amulet/io/binary_writer.hpp +30 -0
- amulet/level/java/_raw/java_chunk_decode.cpp +533 -0
- amulet/level/java/_raw/java_chunk_decode.hpp +23 -0
- amulet/level/java/_raw/java_chunk_encode.cpp +25 -0
- amulet/level/java/_raw/java_chunk_encode.hpp +23 -0
- amulet/level/java/chunk_components/data_version_component.cpp +32 -0
- amulet/level/java/chunk_components/data_version_component.hpp +31 -0
- amulet/level/java/chunk_components/java_raw_chunk_component.cpp +56 -0
- amulet/level/java/chunk_components/java_raw_chunk_component.hpp +45 -0
- amulet/level/java/java_chunk.cpp +170 -0
- amulet/level/java/java_chunk.hpp +141 -0
- amulet/level/java/long_array.hpp +175 -0
- amulet/palette/biome_palette.hpp +85 -0
- amulet/palette/block_palette.cpp +32 -0
- amulet/palette/block_palette.hpp +93 -0
- amulet/pybind11/collections.hpp +76 -0
- amulet/pybind11/py_module.hpp +69 -0
- amulet/pybind11/python.hpp +14 -0
- amulet/pybind11/types.hpp +17 -0
- amulet/utils/numpy.hpp +36 -0
- amulet/version.py.cpp +281 -0
- {amulet_core-2.0a5.dist-info → amulet_core-2.0a6.dist-info}/METADATA +2 -2
- {amulet_core-2.0a5.dist-info → amulet_core-2.0a6.dist-info}/RECORD +50 -7
- {amulet_core-2.0a5.dist-info → amulet_core-2.0a6.dist-info}/WHEEL +0 -0
- {amulet_core-2.0a5.dist-info → amulet_core-2.0a6.dist-info}/entry_points.txt +0 -0
- {amulet_core-2.0a5.dist-info → amulet_core-2.0a6.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <memory>
|
|
4
|
+
|
|
5
|
+
#include <pybind11/pybind11.h>
|
|
6
|
+
|
|
7
|
+
#include "mapping.py.hpp"
|
|
8
|
+
|
|
9
|
+
namespace py = pybind11;
|
|
10
|
+
|
|
11
|
+
namespace Amulet {
|
|
12
|
+
namespace collections {
|
|
13
|
+
template <typename clsT>
|
|
14
|
+
void PyMutableMapping_pop(clsT cls) {
|
|
15
|
+
py::object marker = py::module::import("builtins").attr("Ellipsis");
|
|
16
|
+
cls.def(
|
|
17
|
+
"pop",
|
|
18
|
+
[marker](py::object self, py::object key, py::object default_) {
|
|
19
|
+
py::object value;
|
|
20
|
+
try {
|
|
21
|
+
value = self.attr("__getitem__")(key);
|
|
22
|
+
}
|
|
23
|
+
catch (const py::error_already_set& e) {
|
|
24
|
+
if (e.matches(PyExc_KeyError)) {
|
|
25
|
+
if (default_.is(marker)) {
|
|
26
|
+
throw;
|
|
27
|
+
}
|
|
28
|
+
return default_;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
throw;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
self.attr("__delitem__")(key);
|
|
35
|
+
return value;
|
|
36
|
+
},
|
|
37
|
+
py::arg("key"),
|
|
38
|
+
py::arg("default") = marker
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
template <typename clsT>
|
|
43
|
+
void PyMutableMapping_popitem(clsT cls) {
|
|
44
|
+
py::object iter = py::module::import("builtins").attr("iter");
|
|
45
|
+
py::object next = py::module::import("builtins").attr("next");
|
|
46
|
+
cls.def(
|
|
47
|
+
"popitem",
|
|
48
|
+
[iter, next](py::object self) {
|
|
49
|
+
py::object key;
|
|
50
|
+
try {
|
|
51
|
+
key = next(iter(self));
|
|
52
|
+
}
|
|
53
|
+
catch (const py::error_already_set& e) {
|
|
54
|
+
if (e.matches(PyExc_StopIteration)) {
|
|
55
|
+
throw py::key_error();
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
throw;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
py::object value = self.attr("__getitem__")(key);
|
|
62
|
+
self.attr("__delitem__")(key);
|
|
63
|
+
return std::make_pair(key, value);
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
template <typename clsT>
|
|
69
|
+
void PyMutableMapping_clear(clsT cls) {
|
|
70
|
+
cls.def(
|
|
71
|
+
"clear",
|
|
72
|
+
[](py::object self) {
|
|
73
|
+
try {
|
|
74
|
+
while (true) {
|
|
75
|
+
self.attr("popitem")();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch (const py::error_already_set& e) {
|
|
79
|
+
if (!e.matches(PyExc_KeyError)) {
|
|
80
|
+
throw;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
template <typename clsT>
|
|
88
|
+
void PyMutableMapping_update(clsT cls) {
|
|
89
|
+
py::object isinstance = py::module::import("builtins").attr("isinstance");
|
|
90
|
+
py::object hasattr = py::module::import("builtins").attr("hasattr");
|
|
91
|
+
py::object PyMapping = py::module::import("collections.abc").attr("Mapping");
|
|
92
|
+
cls.def(
|
|
93
|
+
"update",
|
|
94
|
+
[
|
|
95
|
+
isinstance,
|
|
96
|
+
hasattr,
|
|
97
|
+
PyMapping
|
|
98
|
+
](
|
|
99
|
+
py::object self,
|
|
100
|
+
py::object other,
|
|
101
|
+
py::kwargs kwargs
|
|
102
|
+
) {
|
|
103
|
+
if (isinstance(other, PyMapping)) {
|
|
104
|
+
for (auto it = other.begin(); it != other.end(); it++) {
|
|
105
|
+
self.attr("__setitem__")(*it, other.attr("__getitem__")(*it));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else if (hasattr(other, "keys")) {
|
|
109
|
+
py::object keys = other.attr("keys")();
|
|
110
|
+
for (auto it = keys.begin(); it != keys.end(); it++) {
|
|
111
|
+
self.attr("__setitem__")(*it, other.attr("__getitem__")(*it));
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
for (auto it = other.begin(); it != other.end(); it++) {
|
|
116
|
+
self.attr("__setitem__")(
|
|
117
|
+
*it->attr("__getitem__")(0),
|
|
118
|
+
*it->attr("__getitem__")(1)
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
py::object items = kwargs.attr("items")();
|
|
123
|
+
for (auto it = items.begin(); it != items.end(); it++) {
|
|
124
|
+
self.attr("__setitem__")(
|
|
125
|
+
*it->attr("__getitem__")(0),
|
|
126
|
+
*it->attr("__getitem__")(1)
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
},
|
|
131
|
+
py::arg("other") = py::tuple()
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
template <typename clsT>
|
|
136
|
+
void PyMutableMapping_setdefault(clsT cls) {
|
|
137
|
+
cls.def(
|
|
138
|
+
"setdefault",
|
|
139
|
+
[](py::object self, py::object key, py::object default_ = py::none()) {
|
|
140
|
+
try {
|
|
141
|
+
return self.attr("__getitem__")(key);
|
|
142
|
+
}
|
|
143
|
+
catch (const py::error_already_set& e) {
|
|
144
|
+
if (e.matches(PyExc_KeyError)) {
|
|
145
|
+
self.attr("__setitem__")(key, default_);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
throw;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return default_;
|
|
152
|
+
}
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
template <typename clsT>
|
|
157
|
+
void PyMutableMapping_register(clsT cls) {
|
|
158
|
+
py::module::import("collections.abc").attr("MutableMapping").attr("register")(cls);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
class MutableMapping : public Mapping {
|
|
162
|
+
public:
|
|
163
|
+
virtual ~MutableMapping() {};
|
|
164
|
+
virtual void setitem(py::object py_key, py::object py_value) = 0;
|
|
165
|
+
virtual void delitem(py::object py_key) = 0;
|
|
166
|
+
virtual void clear() = 0;
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
template <typename mapT>
|
|
170
|
+
class Map : public MutableMapping {
|
|
171
|
+
private:
|
|
172
|
+
py::object _owner;
|
|
173
|
+
mapT& _map;
|
|
174
|
+
public:
|
|
175
|
+
Map(
|
|
176
|
+
mapT& map,
|
|
177
|
+
py::object owner = py::none()
|
|
178
|
+
) : _owner(owner), _map(map) {}
|
|
179
|
+
|
|
180
|
+
py::object getitem(py::object py_key) const override {
|
|
181
|
+
return py::cast(_map.at(py_key.cast<typename mapT::key_type>()));
|
|
182
|
+
}
|
|
183
|
+
std::shared_ptr<Iterator> iter() const override {
|
|
184
|
+
return std::make_shared<MapIterator<mapT>>(_map, _owner);
|
|
185
|
+
}
|
|
186
|
+
size_t size() const override {
|
|
187
|
+
return _map.size();
|
|
188
|
+
}
|
|
189
|
+
bool contains(py::object py_key) const override {
|
|
190
|
+
return _map.contains(py_key.cast<typename mapT::key_type>());
|
|
191
|
+
}
|
|
192
|
+
void setitem(py::object py_key, py::object py_value) override {
|
|
193
|
+
_map.insert_or_assign(
|
|
194
|
+
py_key.cast<typename mapT::key_type>(),
|
|
195
|
+
py_value.cast<typename mapT::mapped_type>()
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
void delitem(py::object py_key) override {
|
|
199
|
+
_map.erase(py_key.cast<typename mapT::key_type>());
|
|
200
|
+
}
|
|
201
|
+
void clear() override {
|
|
202
|
+
_map.clear();
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
template <typename mapT>
|
|
207
|
+
static py::object make_map(mapT& value, py::object owner = py::none()) {
|
|
208
|
+
return py::cast(
|
|
209
|
+
static_cast<std::shared_ptr<MutableMapping>>(
|
|
210
|
+
std::make_shared<Map<mapT>>(value, owner)
|
|
211
|
+
)
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <algorithm>
|
|
4
|
+
#include <cstddef>
|
|
5
|
+
#include <memory>
|
|
6
|
+
|
|
7
|
+
#include <pybind11/pybind11.h>
|
|
8
|
+
#include "iterator.py.hpp"
|
|
9
|
+
#include <amulet/pybind11/collections.hpp>
|
|
10
|
+
#include <amulet/pybind11/python.hpp>
|
|
11
|
+
|
|
12
|
+
namespace py = pybind11;
|
|
13
|
+
|
|
14
|
+
namespace Amulet {
|
|
15
|
+
namespace collections {
|
|
16
|
+
|
|
17
|
+
template <typename clsT>
|
|
18
|
+
void Sequence_getitem_slice(clsT cls) {
|
|
19
|
+
cls.def(
|
|
20
|
+
"__getitem__",
|
|
21
|
+
[](py::object self, const py::slice& slice) {
|
|
22
|
+
size_t start = 0, stop = 0, step = 0, slicelength = 0;
|
|
23
|
+
if (!slice.compute(py::len(self), &start, &stop, &step, &slicelength)) {
|
|
24
|
+
throw py::error_already_set();
|
|
25
|
+
}
|
|
26
|
+
py::list out(slicelength);
|
|
27
|
+
py::object getitem = self.attr("__getitem__");
|
|
28
|
+
for (size_t i = 0; i < slicelength; ++i) {
|
|
29
|
+
out[i] = getitem(start);
|
|
30
|
+
start += step;
|
|
31
|
+
}
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
template <typename clsT>
|
|
38
|
+
void Sequence_contains(clsT cls) {
|
|
39
|
+
cls.def(
|
|
40
|
+
"__contains__",
|
|
41
|
+
[](py::object self, py::object value) {
|
|
42
|
+
py::iterator it = py::iter(self);
|
|
43
|
+
while (it != py::iterator::sentinel()) {
|
|
44
|
+
if (py::equals(*it, value)) {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
++it;
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
template <typename elemT = py::object, typename clsT>
|
|
55
|
+
void Sequence_iter(clsT cls) {
|
|
56
|
+
cls.def(
|
|
57
|
+
"__iter__",
|
|
58
|
+
[](py::object self) -> py::collections::Iterator<elemT> {
|
|
59
|
+
return py::cast(
|
|
60
|
+
static_cast<std::shared_ptr<Amulet::collections::Iterator>>(
|
|
61
|
+
std::make_shared<PySequenceIterator>(self, 0, 1)
|
|
62
|
+
)
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
template <typename elemT = py::object, typename clsT>
|
|
69
|
+
void Sequence_reversed(clsT cls) {
|
|
70
|
+
cls.def(
|
|
71
|
+
"__reversed__",
|
|
72
|
+
[](py::object self) -> py::collections::Iterator<elemT> {
|
|
73
|
+
return py::cast(
|
|
74
|
+
static_cast<std::shared_ptr<Amulet::collections::Iterator>>(
|
|
75
|
+
std::make_shared<PySequenceIterator>(self, py::len(self) - 1, -1)
|
|
76
|
+
)
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
template <typename clsT>
|
|
83
|
+
void Sequence_index(clsT cls) {
|
|
84
|
+
cls.def(
|
|
85
|
+
"index",
|
|
86
|
+
[](py::object self, py::object value, Py_ssize_t s_start, Py_ssize_t s_stop) {
|
|
87
|
+
size_t size = py::len(self);
|
|
88
|
+
size_t start;
|
|
89
|
+
size_t stop;
|
|
90
|
+
if (s_start < 0) {
|
|
91
|
+
start = std::max<Py_ssize_t>(0, size + s_start);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
start = s_start;
|
|
95
|
+
}
|
|
96
|
+
if (s_stop < 0) {
|
|
97
|
+
stop = size + s_stop;
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
stop = s_stop;
|
|
101
|
+
}
|
|
102
|
+
py::object getitem = self.attr("__getitem__");
|
|
103
|
+
while (start < stop) {
|
|
104
|
+
py::object obj;
|
|
105
|
+
try {
|
|
106
|
+
obj = getitem(start);
|
|
107
|
+
}
|
|
108
|
+
catch (py::error_already_set& e) {
|
|
109
|
+
if (e.matches(PyExc_IndexError)) {
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
throw;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (py::equals(value, obj)) {
|
|
118
|
+
return start;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
start++;
|
|
122
|
+
}
|
|
123
|
+
throw py::value_error("");
|
|
124
|
+
},
|
|
125
|
+
py::arg("value"), py::arg("start") = 0, py::arg("stop") = std::numeric_limits<Py_ssize_t>::max()
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
template <typename clsT>
|
|
130
|
+
void Sequence_count(clsT cls) {
|
|
131
|
+
cls.def(
|
|
132
|
+
"count",
|
|
133
|
+
[](py::object self, py::object value) {
|
|
134
|
+
size_t count = 0;
|
|
135
|
+
size_t size = py::len(self);
|
|
136
|
+
py::object getitem = self.attr("__getitem__");
|
|
137
|
+
for (size_t i = 0; i < size; ++i) {
|
|
138
|
+
if (py::equals(value, getitem(i))) {
|
|
139
|
+
count++;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return count;
|
|
143
|
+
},
|
|
144
|
+
py::arg("value")
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
template <typename clsT>
|
|
149
|
+
void Sequence_register(clsT cls) {
|
|
150
|
+
py::module::import("collections.abc").attr("Sequence").attr("register")(cls);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
template <typename elemT = py::object, typename clsT>
|
|
154
|
+
void Sequence(clsT cls) {
|
|
155
|
+
Sequence_getitem_slice(cls);
|
|
156
|
+
Sequence_contains(cls);
|
|
157
|
+
Sequence_iter<elemT>(cls);
|
|
158
|
+
Sequence_reversed<elemT>(cls);
|
|
159
|
+
Sequence_index(cls);
|
|
160
|
+
Sequence_count(cls);
|
|
161
|
+
Sequence_register(cls);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <string>
|
|
4
|
+
#include <cstdint>
|
|
5
|
+
#include <cstring>
|
|
6
|
+
#include <algorithm>
|
|
7
|
+
#include <bit>
|
|
8
|
+
#include <functional>
|
|
9
|
+
#include <stdexcept>
|
|
10
|
+
#include <memory>
|
|
11
|
+
|
|
12
|
+
#include <amulet_nbt/io/binary_reader.hpp>
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
namespace Amulet {
|
|
16
|
+
class BinaryReader: public AmuletNBT::BinaryReader {
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
public:
|
|
20
|
+
BinaryReader(
|
|
21
|
+
const std::string& input,
|
|
22
|
+
size_t& position
|
|
23
|
+
) : AmuletNBT::BinaryReader(input, position, std::endian::little, [](const std::string& value) {return value; }) {}
|
|
24
|
+
|
|
25
|
+
std::string readSizeAndBytes() {
|
|
26
|
+
std::uint64_t length;
|
|
27
|
+
readNumericInto<std::uint64_t>(length);
|
|
28
|
+
// Ensure the buffer is long enough
|
|
29
|
+
if (position + length > data.size()) {
|
|
30
|
+
throw std::out_of_range("Cannot read string of length " + std::to_string(length) + " at position " + std::to_string(position));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
std::string value = data.substr(position, length);
|
|
34
|
+
position += length;
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
template <class T>
|
|
40
|
+
std::shared_ptr<T> deserialise(const std::string& data){
|
|
41
|
+
size_t position = 0;
|
|
42
|
+
BinaryReader reader(data, position);
|
|
43
|
+
return T::deserialise(reader);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <string>
|
|
4
|
+
#include <cstdint>
|
|
5
|
+
#include <cstring>
|
|
6
|
+
#include <algorithm>
|
|
7
|
+
#include <bit>
|
|
8
|
+
#include <functional>
|
|
9
|
+
|
|
10
|
+
#include <amulet_nbt/io/binary_writer.hpp>
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
namespace Amulet {
|
|
14
|
+
class BinaryWriter: public AmuletNBT::BinaryWriter {
|
|
15
|
+
public:
|
|
16
|
+
BinaryWriter(): AmuletNBT::BinaryWriter(std::endian::little, [](const std::string& value) {return value; }) {}
|
|
17
|
+
|
|
18
|
+
void writeSizeAndBytes(const std::string& value) {
|
|
19
|
+
writeNumeric<std::uint64_t>(value.size());
|
|
20
|
+
data.append(value);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
template <typename T>
|
|
25
|
+
std::string serialise(const T& obj){
|
|
26
|
+
BinaryWriter writer;
|
|
27
|
+
obj.serialise(writer);
|
|
28
|
+
return writer.getBuffer();
|
|
29
|
+
}
|
|
30
|
+
}
|