1 /*
2  * This file was automatically generated by sel-utils and
3  * released under the MIT License.
4  * 
5  * License: https://github.com/sel-project/sel-utils/blob/master/LICENSE
6  * Repository: https://github.com/sel-project/sel-utils
7  * Generated from https://github.com/sel-project/sel-utils/blob/master/xml/protocol/pocket113.xml
8  */
9 module sul.protocol.pocket113.types;
10 
11 import std.bitmanip : write, peek;
12 static import std.conv;
13 import std.system : Endian;
14 import std.typecons : Tuple;
15 import std.uuid : UUID;
16 
17 import sul.utils.buffer;
18 import sul.utils.var;
19 
20 static if(__traits(compiles, { import sul.metadata.pocket113; })) import sul.metadata.pocket113;
21 
22 struct LoginBody {
23 
24 	public enum string[] FIELDS = ["chain", "clientData"];
25 
26 	public ubyte[] chain;
27 	public ubyte[] clientData;
28 
29 	public pure nothrow @safe void encode(Buffer o_buffer) {
30 		Buffer buffer = new Buffer();
31 		with(buffer) {
32 			writeLittleEndianUint(cast(uint)chain.length); writeBytes(chain);
33 			writeLittleEndianUint(cast(uint)clientData.length); writeBytes(clientData);
34 		}
35 		with(o_buffer){ writeBytes(varuint.encode(cast(uint)buffer._buffer.length)); }
36 		o_buffer.writeBytes(buffer._buffer);
37 	}
38 
39 	public pure nothrow @safe void decode(Buffer o_buffer) {
40 		Buffer buffer = new Buffer();
41 		with(o_buffer) {
42 			immutable _length=varuint.decode(_buffer, &_index);
43 			buffer._buffer = readBytes(_length);
44 		}
45 		with(buffer) {
46 			chain.length=readLittleEndianUint(); if(_buffer.length>=_index+chain.length){ chain=_buffer[_index.._index+chain.length].dup; _index+=chain.length; }
47 			clientData.length=readLittleEndianUint(); if(_buffer.length>=_index+clientData.length){ clientData=_buffer[_index.._index+clientData.length].dup; _index+=clientData.length; }
48 		}
49 	}
50 
51 	public string toString() {
52 		return "LoginBody(chain: " ~ std.conv.to!string(this.chain) ~ ", clientData: " ~ std.conv.to!string(this.clientData) ~ ")";
53 	}
54 
55 }
56 
57 struct PackWithSize {
58 
59 	public enum string[] FIELDS = ["id", "vers", "size"];
60 
61 	public string id;
62 	public string vers;
63 	public ulong size;
64 
65 	public pure nothrow @safe void encode(Buffer buffer) {
66 		with(buffer) {
67 			writeBytes(varuint.encode(cast(uint)id.length)); writeString(id);
68 			writeBytes(varuint.encode(cast(uint)vers.length)); writeString(vers);
69 			writeLittleEndianUlong(size);
70 		}
71 	}
72 
73 	public pure nothrow @safe void decode(Buffer buffer) {
74 		with(buffer) {
75 			uint aq=varuint.decode(_buffer, &_index); id=readString(aq);
76 			uint dvc=varuint.decode(_buffer, &_index); vers=readString(dvc);
77 			size=readLittleEndianUlong();
78 		}
79 	}
80 
81 	public string toString() {
82 		return "PackWithSize(id: " ~ std.conv.to!string(this.id) ~ ", vers: " ~ std.conv.to!string(this.vers) ~ ", size: " ~ std.conv.to!string(this.size) ~ ")";
83 	}
84 
85 }
86 
87 struct Pack {
88 
89 	public enum string[] FIELDS = ["id", "vers"];
90 
91 	public string id;
92 	public string vers;
93 
94 	public pure nothrow @safe void encode(Buffer buffer) {
95 		with(buffer) {
96 			writeBytes(varuint.encode(cast(uint)id.length)); writeString(id);
97 			writeBytes(varuint.encode(cast(uint)vers.length)); writeString(vers);
98 		}
99 	}
100 
101 	public pure nothrow @safe void decode(Buffer buffer) {
102 		with(buffer) {
103 			uint aq=varuint.decode(_buffer, &_index); id=readString(aq);
104 			uint dvc=varuint.decode(_buffer, &_index); vers=readString(dvc);
105 		}
106 	}
107 
108 	public string toString() {
109 		return "Pack(id: " ~ std.conv.to!string(this.id) ~ ", vers: " ~ std.conv.to!string(this.vers) ~ ")";
110 	}
111 
112 }
113 
114 struct Slot {
115 
116 	public enum string[] FIELDS = ["id", "metaAndCount", "nbt", "canPlaceOn", "canDestroy"];
117 
118 	public int id;
119 	public int metaAndCount;
120 	public ubyte[] nbt;
121 	public string[] canPlaceOn;
122 	public string[] canDestroy;
123 
124 	public pure nothrow @safe void encode(Buffer buffer) {
125 		with(buffer) {
126 			writeBytes(varint.encode(id));
127 			if(id>0){ writeBytes(varint.encode(metaAndCount)); }
128 			if(id>0){ writeLittleEndianUshort(cast(ushort)nbt.length); writeBytes(nbt); }
129 			writeBytes(varuint.encode(cast(uint)canPlaceOn.length)); foreach(yfuxyvb;canPlaceOn){ writeBytes(varuint.encode(cast(uint)yfuxyvb.length)); writeString(yfuxyvb); }
130 			writeBytes(varuint.encode(cast(uint)canDestroy.length)); foreach(yfrvdje;canDestroy){ writeBytes(varuint.encode(cast(uint)yfrvdje.length)); writeString(yfrvdje); }
131 		}
132 	}
133 
134 	public pure nothrow @safe void decode(Buffer buffer) {
135 		with(buffer) {
136 			id=varint.decode(_buffer, &_index);
137 			if(id>0){ metaAndCount=varint.decode(_buffer, &_index); }
138 			if(id>0){ nbt.length=readLittleEndianUshort(); if(_buffer.length>=_index+nbt.length){ nbt=_buffer[_index.._index+nbt.length].dup; _index+=nbt.length; } }
139 			canPlaceOn.length=varuint.decode(_buffer, &_index); foreach(ref yfuxyvb;canPlaceOn){ uint ezely=varuint.decode(_buffer, &_index); yfuxyvb=readString(ezely); }
140 			canDestroy.length=varuint.decode(_buffer, &_index); foreach(ref yfrvdje;canDestroy){ uint ezdrz=varuint.decode(_buffer, &_index); yfrvdje=readString(ezdrz); }
141 		}
142 	}
143 
144 	public string toString() {
145 		return "Slot(id: " ~ std.conv.to!string(this.id) ~ ", metaAndCount: " ~ std.conv.to!string(this.metaAndCount) ~ ", nbt: " ~ std.conv.to!string(this.nbt) ~ ", canPlaceOn: " ~ std.conv.to!string(this.canPlaceOn) ~ ", canDestroy: " ~ std.conv.to!string(this.canDestroy) ~ ")";
146 	}
147 
148 }
149 
150 struct Attribute {
151 
152 	public enum string[] FIELDS = ["min", "max", "value", "def", "name"];
153 
154 	public float min;
155 	public float max;
156 	public float value;
157 	public float def;
158 	public string name;
159 
160 	public pure nothrow @safe void encode(Buffer buffer) {
161 		with(buffer) {
162 			writeLittleEndianFloat(min);
163 			writeLittleEndianFloat(max);
164 			writeLittleEndianFloat(value);
165 			writeLittleEndianFloat(def);
166 			writeBytes(varuint.encode(cast(uint)name.length)); writeString(name);
167 		}
168 	}
169 
170 	public pure nothrow @safe void decode(Buffer buffer) {
171 		with(buffer) {
172 			min=readLittleEndianFloat();
173 			max=readLittleEndianFloat();
174 			value=readLittleEndianFloat();
175 			def=readLittleEndianFloat();
176 			uint bfz=varuint.decode(_buffer, &_index); name=readString(bfz);
177 		}
178 	}
179 
180 	public string toString() {
181 		return "Attribute(min: " ~ std.conv.to!string(this.min) ~ ", max: " ~ std.conv.to!string(this.max) ~ ", value: " ~ std.conv.to!string(this.value) ~ ", def: " ~ std.conv.to!string(this.def) ~ ", name: " ~ std.conv.to!string(this.name) ~ ")";
182 	}
183 
184 }
185 
186 struct BlockPosition {
187 
188 	public enum string[] FIELDS = ["x", "y", "z"];
189 
190 	public int x;
191 	public uint y;
192 	public int z;
193 
194 	public pure nothrow @safe void encode(Buffer buffer) {
195 		with(buffer) {
196 			writeBytes(varint.encode(x));
197 			writeBytes(varuint.encode(y));
198 			writeBytes(varint.encode(z));
199 		}
200 	}
201 
202 	public pure nothrow @safe void decode(Buffer buffer) {
203 		with(buffer) {
204 			x=varint.decode(_buffer, &_index);
205 			y=varuint.decode(_buffer, &_index);
206 			z=varint.decode(_buffer, &_index);
207 		}
208 	}
209 
210 	public string toString() {
211 		return "BlockPosition(x: " ~ std.conv.to!string(this.x) ~ ", y: " ~ std.conv.to!string(this.y) ~ ", z: " ~ std.conv.to!string(this.z) ~ ")";
212 	}
213 
214 }
215 
216 struct McpeUuid {
217 
218 	public enum string[] FIELDS = ["mostSignificantBits", "leastSignificantBits"];
219 
220 	public long mostSignificantBits;
221 	public long leastSignificantBits;
222 
223 	public pure nothrow @safe void encode(Buffer buffer) {
224 		with(buffer) {
225 			writeLittleEndianLong(mostSignificantBits);
226 			writeLittleEndianLong(leastSignificantBits);
227 		}
228 	}
229 
230 	public pure nothrow @safe void decode(Buffer buffer) {
231 		with(buffer) {
232 			mostSignificantBits=readLittleEndianLong();
233 			leastSignificantBits=readLittleEndianLong();
234 		}
235 	}
236 
237 	public string toString() {
238 		return "McpeUuid(mostSignificantBits: " ~ std.conv.to!string(this.mostSignificantBits) ~ ", leastSignificantBits: " ~ std.conv.to!string(this.leastSignificantBits) ~ ")";
239 	}
240 
241 }
242 
243 struct Skin {
244 
245 	public enum string[] FIELDS = ["name", "data"];
246 
247 	public string name;
248 	public ubyte[] data;
249 
250 	public pure nothrow @safe void encode(Buffer buffer) {
251 		with(buffer) {
252 			writeBytes(varuint.encode(cast(uint)name.length)); writeString(name);
253 			writeBytes(varuint.encode(cast(uint)data.length)); writeBytes(data);
254 		}
255 	}
256 
257 	public pure nothrow @safe void decode(Buffer buffer) {
258 		with(buffer) {
259 			uint bfz=varuint.decode(_buffer, &_index); name=readString(bfz);
260 			data.length=varuint.decode(_buffer, &_index); if(_buffer.length>=_index+data.length){ data=_buffer[_index.._index+data.length].dup; _index+=data.length; }
261 		}
262 	}
263 
264 	public string toString() {
265 		return "Skin(name: " ~ std.conv.to!string(this.name) ~ ", data: " ~ std.conv.to!string(this.data) ~ ")";
266 	}
267 
268 }
269 
270 struct PlayerList {
271 
272 	public enum string[] FIELDS = ["uuid", "entityId", "displayName", "skin"];
273 
274 	public sul.protocol.pocket113.types.McpeUuid uuid;
275 	public long entityId;
276 	public string displayName;
277 	public sul.protocol.pocket113.types.Skin skin;
278 
279 	public pure nothrow @safe void encode(Buffer buffer) {
280 		with(buffer) {
281 			uuid.encode(bufferInstance);
282 			writeBytes(varlong.encode(entityId));
283 			writeBytes(varuint.encode(cast(uint)displayName.length)); writeString(displayName);
284 			skin.encode(bufferInstance);
285 		}
286 	}
287 
288 	public pure nothrow @safe void decode(Buffer buffer) {
289 		with(buffer) {
290 			uuid.decode(bufferInstance);
291 			entityId=varlong.decode(_buffer, &_index);
292 			uint zlcxe5bu=varuint.decode(_buffer, &_index); displayName=readString(zlcxe5bu);
293 			skin.decode(bufferInstance);
294 		}
295 	}
296 
297 	public string toString() {
298 		return "PlayerList(uuid: " ~ std.conv.to!string(this.uuid) ~ ", entityId: " ~ std.conv.to!string(this.entityId) ~ ", displayName: " ~ std.conv.to!string(this.displayName) ~ ", skin: " ~ std.conv.to!string(this.skin) ~ ")";
299 	}
300 
301 }
302 
303 struct Link {
304 
305 	// action
306 	public enum ubyte ADD = 0;
307 	public enum ubyte RIDE = 1;
308 	public enum ubyte REMOVE = 2;
309 
310 	public enum string[] FIELDS = ["from", "to", "action"];
311 
312 	public long from;
313 	public long to;
314 	public ubyte action;
315 
316 	public pure nothrow @safe void encode(Buffer buffer) {
317 		with(buffer) {
318 			writeBytes(varlong.encode(from));
319 			writeBytes(varlong.encode(to));
320 			writeBigEndianUbyte(action);
321 		}
322 	}
323 
324 	public pure nothrow @safe void decode(Buffer buffer) {
325 		with(buffer) {
326 			from=varlong.decode(_buffer, &_index);
327 			to=varlong.decode(_buffer, &_index);
328 			action=readBigEndianUbyte();
329 		}
330 	}
331 
332 	public string toString() {
333 		return "Link(from: " ~ std.conv.to!string(this.from) ~ ", to: " ~ std.conv.to!string(this.to) ~ ", action: " ~ std.conv.to!string(this.action) ~ ")";
334 	}
335 
336 }
337 
338 struct Recipe {
339 
340 	// type
341 	public enum int SHAPELESS = 0;
342 	public enum int SHAPED = 1;
343 	public enum int FURNACE = 2;
344 	public enum int FURNACE_DATA = 3;
345 	public enum int MULTI = 4;
346 
347 	public enum string[] FIELDS = ["type", "data"];
348 
349 	public int type;
350 	public ubyte[] data;
351 
352 	public pure nothrow @safe void encode(Buffer buffer) {
353 		with(buffer) {
354 			writeBytes(varint.encode(type));
355 			writeBytes(data);
356 		}
357 	}
358 
359 	public pure nothrow @safe void decode(Buffer buffer) {
360 		with(buffer) {
361 			type=varint.decode(_buffer, &_index);
362 			data=_buffer[_index..$].dup; _index=_buffer.length;
363 		}
364 	}
365 
366 	public string toString() {
367 		return "Recipe(type: " ~ std.conv.to!string(this.type) ~ ", data: " ~ std.conv.to!string(this.data) ~ ")";
368 	}
369 
370 }
371 
372 struct ChunkData {
373 
374 	public enum string[] FIELDS = ["sections", "heights", "biomes", "borders", "extraData", "blockEntities"];
375 
376 	public sul.protocol.pocket113.types.Section[] sections;
377 	public ushort[256] heights;
378 	public ubyte[256] biomes;
379 	public ubyte[] borders;
380 	public sul.protocol.pocket113.types.ExtraData[] extraData;
381 	public ubyte[] blockEntities;
382 
383 	public pure nothrow @safe void encode(Buffer o_buffer) {
384 		Buffer buffer = new Buffer();
385 		with(buffer) {
386 			writeBytes(varuint.encode(cast(uint)sections.length)); foreach(cvdlbm;sections){ cvdlbm.encode(bufferInstance); }
387 			foreach(avzhc;heights){ writeBigEndianUshort(avzhc); }
388 			writeBytes(biomes);
389 			writeBytes(varuint.encode(cast(uint)borders.length)); writeBytes(borders);
390 			writeBytes(varuint.encode(cast(uint)extraData.length)); foreach(zhcfyr;extraData){ zhcfyr.encode(bufferInstance); }
391 			writeBytes(blockEntities);
392 		}
393 		with(o_buffer){ writeBytes(varuint.encode(cast(uint)buffer._buffer.length)); }
394 		o_buffer.writeBytes(buffer._buffer);
395 	}
396 
397 	public pure nothrow @safe void decode(Buffer o_buffer) {
398 		Buffer buffer = new Buffer();
399 		with(o_buffer) {
400 			immutable _length=varuint.decode(_buffer, &_index);
401 			buffer._buffer = readBytes(_length);
402 		}
403 		with(buffer) {
404 			sections.length=varuint.decode(_buffer, &_index); foreach(ref cvdlbm;sections){ cvdlbm.decode(bufferInstance); }
405 			foreach(ref avzhc;heights){ avzhc=readBigEndianUshort(); }
406 			if(_buffer.length>=_index+biomes.length){ biomes=_buffer[_index.._index+biomes.length].dup; _index+=biomes.length; }
407 			borders.length=varuint.decode(_buffer, &_index); if(_buffer.length>=_index+borders.length){ borders=_buffer[_index.._index+borders.length].dup; _index+=borders.length; }
408 			extraData.length=varuint.decode(_buffer, &_index); foreach(ref zhcfyr;extraData){ zhcfyr.decode(bufferInstance); }
409 			blockEntities=_buffer[_index..$].dup; _index=_buffer.length;
410 		}
411 	}
412 
413 	public string toString() {
414 		return "ChunkData(sections: " ~ std.conv.to!string(this.sections) ~ ", heights: " ~ std.conv.to!string(this.heights) ~ ", biomes: " ~ std.conv.to!string(this.biomes) ~ ", borders: " ~ std.conv.to!string(this.borders) ~ ", extraData: " ~ std.conv.to!string(this.extraData) ~ ", blockEntities: " ~ std.conv.to!string(this.blockEntities) ~ ")";
415 	}
416 
417 }
418 
419 struct Section {
420 
421 	public enum string[] FIELDS = ["storageVersion", "blockIds", "blockMetas", "skyLight", "blockLight"];
422 
423 	public ubyte storageVersion = 0;
424 	public ubyte[4096] blockIds;
425 	public ubyte[2048] blockMetas;
426 	public ubyte[2048] skyLight;
427 	public ubyte[2048] blockLight;
428 
429 	public pure nothrow @safe void encode(Buffer buffer) {
430 		with(buffer) {
431 			writeBigEndianUbyte(storageVersion);
432 			writeBytes(blockIds);
433 			writeBytes(blockMetas);
434 			writeBytes(skyLight);
435 			writeBytes(blockLight);
436 		}
437 	}
438 
439 	public pure nothrow @safe void decode(Buffer buffer) {
440 		with(buffer) {
441 			storageVersion=readBigEndianUbyte();
442 			if(_buffer.length>=_index+blockIds.length){ blockIds=_buffer[_index.._index+blockIds.length].dup; _index+=blockIds.length; }
443 			if(_buffer.length>=_index+blockMetas.length){ blockMetas=_buffer[_index.._index+blockMetas.length].dup; _index+=blockMetas.length; }
444 			if(_buffer.length>=_index+skyLight.length){ skyLight=_buffer[_index.._index+skyLight.length].dup; _index+=skyLight.length; }
445 			if(_buffer.length>=_index+blockLight.length){ blockLight=_buffer[_index.._index+blockLight.length].dup; _index+=blockLight.length; }
446 		}
447 	}
448 
449 	public string toString() {
450 		return "Section(storageVersion: " ~ std.conv.to!string(this.storageVersion) ~ ", blockIds: " ~ std.conv.to!string(this.blockIds) ~ ", blockMetas: " ~ std.conv.to!string(this.blockMetas) ~ ", skyLight: " ~ std.conv.to!string(this.skyLight) ~ ", blockLight: " ~ std.conv.to!string(this.blockLight) ~ ")";
451 	}
452 
453 }
454 
455 struct ExtraData {
456 
457 	public enum string[] FIELDS = ["key", "value"];
458 
459 	public uint key;
460 	public ushort value;
461 
462 	public pure nothrow @safe void encode(Buffer buffer) {
463 		with(buffer) {
464 			writeBytes(varuint.encode(key));
465 			writeLittleEndianUshort(value);
466 		}
467 	}
468 
469 	public pure nothrow @safe void decode(Buffer buffer) {
470 		with(buffer) {
471 			key=varuint.decode(_buffer, &_index);
472 			value=readLittleEndianUshort();
473 		}
474 	}
475 
476 	public string toString() {
477 		return "ExtraData(key: " ~ std.conv.to!string(this.key) ~ ", value: " ~ std.conv.to!string(this.value) ~ ")";
478 	}
479 
480 }
481 
482 struct Decoration {
483 
484 	public enum string[] FIELDS = ["rotationAndIcon", "position", "label", "color"];
485 
486 	public int rotationAndIcon;
487 	public Tuple!(ubyte, "x", ubyte, "z") position;
488 	public string label;
489 	public uint color;
490 
491 	public pure nothrow @safe void encode(Buffer buffer) {
492 		with(buffer) {
493 			writeBytes(varint.encode(rotationAndIcon));
494 			writeBigEndianUbyte(position.x); writeBigEndianUbyte(position.z);
495 			writeBytes(varuint.encode(cast(uint)label.length)); writeString(label);
496 			writeLittleEndianUint(color);
497 		}
498 	}
499 
500 	public pure nothrow @safe void decode(Buffer buffer) {
501 		with(buffer) {
502 			rotationAndIcon=varint.decode(_buffer, &_index);
503 			position.x=readBigEndianUbyte(); position.z=readBigEndianUbyte();
504 			uint bfzw=varuint.decode(_buffer, &_index); label=readString(bfzw);
505 			color=readLittleEndianUint();
506 		}
507 	}
508 
509 	public string toString() {
510 		return "Decoration(rotationAndIcon: " ~ std.conv.to!string(this.rotationAndIcon) ~ ", position: " ~ std.conv.to!string(this.position) ~ ", label: " ~ std.conv.to!string(this.label) ~ ", color: " ~ std.conv.to!string(this.color) ~ ")";
511 	}
512 
513 }
514 
515 struct Rule {
516 
517 	// name
518 	public enum string COMMAND_BLOCK_OUTPUT = "commandblockoutput";
519 	public enum string DO_DAYLIGHT_CYCLE = "dodaylightcycle";
520 	public enum string DO_ENTITY_DROPS = "doentitydrops";
521 	public enum string DO_FIRE_TICK = "dofiretick";
522 	public enum string DO_MOB_LOOT = "domobloot";
523 	public enum string DO_MOB_SPAWNING = "domobspawning";
524 	public enum string DO_TILE_DROPS = "dotiledrops";
525 	public enum string DO_WEATHER_CYCLE = "doweathercycle";
526 	public enum string DROWNING_DAMAGE = "drowningdamage";
527 	public enum string FALL_DAMAGE = "falldamage";
528 	public enum string FIRE_DAMAGE = "firedamage";
529 	public enum string KEEP_INVENTORY = "keepinventory";
530 	public enum string MOB_GRIEFING = "mobgriefing";
531 	public enum string PVP = "pvp";
532 	public enum string SEND_COMMAND_FEEDBACK = "sendcommandfeedback";
533 
534 	// type
535 	public enum ubyte BOOLEAN = 1;
536 	public enum ubyte INTEGER = 2;
537 	public enum ubyte FLOATING = 3;
538 
539 	public enum string[] FIELDS = ["name", "type", "booleanValue", "integerValue", "floatingValue"];
540 
541 	public string name;
542 	public ubyte type;
543 	public bool booleanValue;
544 	public int integerValue;
545 	public float floatingValue;
546 
547 	public pure nothrow @safe void encode(Buffer buffer) {
548 		with(buffer) {
549 			writeBytes(varuint.encode(cast(uint)name.length)); writeString(name);
550 			writeBigEndianUbyte(type);
551 			if(type==1){ writeBigEndianBool(booleanValue); }
552 			if(type==2){ writeBigEndianInt(integerValue); }
553 			if(type==3){ writeLittleEndianFloat(floatingValue); }
554 		}
555 	}
556 
557 	public pure nothrow @safe void decode(Buffer buffer) {
558 		with(buffer) {
559 			uint bfz=varuint.decode(_buffer, &_index); name=readString(bfz);
560 			type=readBigEndianUbyte();
561 			if(type==1){ booleanValue=readBigEndianBool(); }
562 			if(type==2){ integerValue=readBigEndianInt(); }
563 			if(type==3){ floatingValue=readLittleEndianFloat(); }
564 		}
565 	}
566 
567 	public string toString() {
568 		return "Rule(name: " ~ std.conv.to!string(this.name) ~ ", type: " ~ std.conv.to!string(this.type) ~ ", booleanValue: " ~ std.conv.to!string(this.booleanValue) ~ ", integerValue: " ~ std.conv.to!string(this.integerValue) ~ ", floatingValue: " ~ std.conv.to!string(this.floatingValue) ~ ")";
569 	}
570 
571 }
572