blob: 606823de7e3c8676754bf093d6df908a30b0ad7b [file] [log] [blame]
Jens Geyerd5436f52014-10-03 19:50:38 +02001(*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *)
19
20{$SCOPEDENUMS ON}
21
22unit Thrift.Protocol;
23
24interface
25
26uses
27 Classes,
28 SysUtils,
29 Contnrs,
30 Thrift.Stream,
31 Thrift.Collections,
32 Thrift.Transport;
33
34type
35
36 TType = (
37 Stop = 0,
38 Void = 1,
39 Bool_ = 2,
40 Byte_ = 3,
41 Double_ = 4,
42 I16 = 6,
43 I32 = 8,
44 I64 = 10,
45 String_ = 11,
46 Struct = 12,
47 Map = 13,
48 Set_ = 14,
49 List = 15
50 );
51
52 TMessageType = (
53 Call = 1,
54 Reply = 2,
55 Exception = 3,
56 Oneway = 4
57 );
58
Jens Geyerf0e63312015-03-01 18:47:49 +010059const
60 VALID_TTYPES = [
61 TType.Stop, TType.Void,
62 TType.Bool_, TType.Byte_, TType.Double_, TType.I16, TType.I32, TType.I64, TType.String_,
63 TType.Struct, TType.Map, TType.Set_, TType.List
64 ];
65
66 VALID_MESSAGETYPES = [Low(TMessageType)..High(TMessageType)];
67
68type
Jens Geyerd5436f52014-10-03 19:50:38 +020069 IProtocol = interface;
70 IStruct = interface;
71
72 IProtocolFactory = interface
73 ['{7CD64A10-4E9F-4E99-93BF-708A31F4A67B}']
74 function GetProtocol( const trans: ITransport): IProtocol;
75 end;
76
77 TThriftStringBuilder = class( TStringBuilder)
78 public
79 function Append(const Value: TBytes): TStringBuilder; overload;
80 function Append(const Value: IThriftContainer): TStringBuilder; overload;
81 end;
82
83 TProtocolException = class( Exception )
84 public
85 const // TODO(jensg): change into enum
86 UNKNOWN : Integer = 0;
87 INVALID_DATA : Integer = 1;
88 NEGATIVE_SIZE : Integer = 2;
89 SIZE_LIMIT : Integer = 3;
90 BAD_VERSION : Integer = 4;
91 NOT_IMPLEMENTED : Integer = 5;
92 DEPTH_LIMIT : Integer = 6;
93 protected
94 FType : Integer;
95 public
96 constructor Create; overload;
97 constructor Create( type_: Integer ); overload;
98 constructor Create( type_: Integer; const msg: string); overload;
99 end;
100
101 IMap = interface
102 ['{30531D97-7E06-4233-B800-C3F53CCD23E7}']
103 function GetKeyType: TType;
104 procedure SetKeyType( Value: TType);
105 function GetValueType: TType;
106 procedure SetValueType( Value: TType);
107 function GetCount: Integer;
108 procedure SetCount( Value: Integer);
109 property KeyType: TType read GetKeyType write SetKeyType;
110 property ValueType: TType read GetValueType write SetValueType;
111 property Count: Integer read GetCount write SetCount;
112 end;
113
114 TMapImpl = class( TInterfacedObject, IMap)
115 private
116 FValueType: TType;
117 FKeyType: TType;
118 FCount: Integer;
119 protected
120 function GetKeyType: TType;
121 procedure SetKeyType( Value: TType);
122 function GetValueType: TType;
123 procedure SetValueType( Value: TType);
124 function GetCount: Integer;
125 procedure SetCount( Value: Integer);
126 public
Jens Geyer96eff172015-03-02 01:30:05 +0100127 constructor Create( AKeyType, AValueType: TType; ACount: Integer); overload;
Jens Geyerd5436f52014-10-03 19:50:38 +0200128 constructor Create; overload;
129 end;
130
131 IList = interface
132 ['{6763E1EA-A934-4472-904F-0083980B9B87}']
133 function GetElementType: TType;
134 procedure SetElementType( Value: TType);
135 function GetCount: Integer;
136 procedure SetCount( Value: Integer);
137 property ElementType: TType read GetElementType write SetElementType;
138 property Count: Integer read GetCount write SetCount;
139 end;
140
141 TListImpl = class( TInterfacedObject, IList)
142 private
143 FElementType: TType;
144 FCount : Integer;
145 protected
146 function GetElementType: TType;
147 procedure SetElementType( Value: TType);
148 function GetCount: Integer;
149 procedure SetCount( Value: Integer);
150 public
151 constructor Create( AElementType: TType; ACount: Integer); overload;
152 constructor Create; overload;
153 end;
154
155 ISet = interface
156 ['{A8671700-7514-4C1E-8A05-62786872005F}']
157 function GetElementType: TType;
158 procedure SetElementType( Value: TType);
159 function GetCount: Integer;
160 procedure SetCount( Value: Integer);
161 property ElementType: TType read GetElementType write SetElementType;
162 property Count: Integer read GetCount write SetCount;
163 end;
164
165 TSetImpl = class( TInterfacedObject, ISet)
166 private
167 FCount: Integer;
168 FElementType: TType;
169 protected
170 function GetElementType: TType;
171 procedure SetElementType( Value: TType);
172 function GetCount: Integer;
173 procedure SetCount( Value: Integer);
174 public
175 constructor Create( AElementType: TType; ACount: Integer); overload;
176 constructor Create; overload;
177 end;
178
179 IMessage = interface
180 ['{9E368B4A-B1FA-43E7-8CF5-56C66D256CA7}']
181 function GetName: string;
182 procedure SetName( const Value: string);
183 function GetType: TMessageType;
184 procedure SetType( Value: TMessageType);
185 function GetSeqID: Integer;
186 procedure SetSeqID( Value: Integer);
187 property Name: string read GetName write SetName;
188 property Type_: TMessageType read GetType write SetType;
189 property SeqID: Integer read GetSeqID write SetSeqID;
190 end;
191
192 TMessageImpl = class( TInterfacedObject, IMessage )
193 private
194 FName: string;
195 FMessageType: TMessageType;
196 FSeqID: Integer;
197 protected
198 function GetName: string;
199 procedure SetName( const Value: string);
200 function GetType: TMessageType;
201 procedure SetType( Value: TMessageType);
202 function GetSeqID: Integer;
203 procedure SetSeqID( Value: Integer);
204 public
205 property Name: string read FName write FName;
206 property Type_: TMessageType read FMessageType write FMessageType;
207 property SeqID: Integer read FSeqID write FSeqID;
208 constructor Create( AName: string; AMessageType: TMessageType; ASeqID: Integer); overload;
209 constructor Create; overload;
210 end;
211
212 IField = interface
213 ['{F0D43BE5-7883-442E-83FF-0580CC632B72}']
214 function GetName: string;
215 procedure SetName( const Value: string);
216 function GetType: TType;
217 procedure SetType( Value: TType);
218 function GetId: SmallInt;
219 procedure SetId( Value: SmallInt);
220 property Name: string read GetName write SetName;
221 property Type_: TType read GetType write SetType;
222 property Id: SmallInt read GetId write SetId;
223 end;
224
225 TFieldImpl = class( TInterfacedObject, IField)
226 private
227 FName : string;
228 FType : TType;
229 FId : SmallInt;
230 protected
231 function GetName: string;
232 procedure SetName( const Value: string);
233 function GetType: TType;
234 procedure SetType( Value: TType);
235 function GetId: SmallInt;
236 procedure SetId( Value: SmallInt);
237 public
238 constructor Create( const AName: string; const AType: TType; AId: SmallInt); overload;
239 constructor Create; overload;
240 end;
241
242 TProtocolUtil = class
243 public
244 class procedure Skip( prot: IProtocol; type_: TType);
245 end;
246
247 IProtocol = interface
248 ['{FD95C151-1527-4C96-8134-B902BFC4B4FC}']
249 function GetTransport: ITransport;
250 procedure WriteMessageBegin( const msg: IMessage);
251 procedure WriteMessageEnd;
252 procedure WriteStructBegin( const struc: IStruct);
253 procedure WriteStructEnd;
254 procedure WriteFieldBegin( const field: IField);
255 procedure WriteFieldEnd;
256 procedure WriteFieldStop;
257 procedure WriteMapBegin( const map: IMap);
258 procedure WriteMapEnd;
259 procedure WriteListBegin( const list: IList);
260 procedure WriteListEnd();
261 procedure WriteSetBegin( const set_: ISet );
262 procedure WriteSetEnd();
263 procedure WriteBool( b: Boolean);
264 procedure WriteByte( b: ShortInt);
265 procedure WriteI16( i16: SmallInt);
266 procedure WriteI32( i32: Integer);
267 procedure WriteI64( const i64: Int64);
268 procedure WriteDouble( const d: Double);
269 procedure WriteString( const s: string );
270 procedure WriteAnsiString( const s: AnsiString);
271 procedure WriteBinary( const b: TBytes);
272
273 function ReadMessageBegin: IMessage;
274 procedure ReadMessageEnd();
275 function ReadStructBegin: IStruct;
276 procedure ReadStructEnd;
277 function ReadFieldBegin: IField;
278 procedure ReadFieldEnd();
279 function ReadMapBegin: IMap;
280 procedure ReadMapEnd();
281 function ReadListBegin: IList;
282 procedure ReadListEnd();
283 function ReadSetBegin: ISet;
284 procedure ReadSetEnd();
285 function ReadBool: Boolean;
286 function ReadByte: ShortInt;
287 function ReadI16: SmallInt;
288 function ReadI32: Integer;
289 function ReadI64: Int64;
290 function ReadDouble:Double;
291 function ReadBinary: TBytes;
292 function ReadString: string;
293 function ReadAnsiString: AnsiString;
294 property Transport: ITransport read GetTransport;
295 end;
296
297 TProtocolImpl = class abstract( TInterfacedObject, IProtocol)
298 protected
299 FTrans : ITransport;
300 function GetTransport: ITransport;
301 public
302 procedure WriteMessageBegin( const msg: IMessage); virtual; abstract;
303 procedure WriteMessageEnd; virtual; abstract;
304 procedure WriteStructBegin( const struc: IStruct); virtual; abstract;
305 procedure WriteStructEnd; virtual; abstract;
306 procedure WriteFieldBegin( const field: IField); virtual; abstract;
307 procedure WriteFieldEnd; virtual; abstract;
308 procedure WriteFieldStop; virtual; abstract;
309 procedure WriteMapBegin( const map: IMap); virtual; abstract;
310 procedure WriteMapEnd; virtual; abstract;
311 procedure WriteListBegin( const list: IList); virtual; abstract;
312 procedure WriteListEnd(); virtual; abstract;
313 procedure WriteSetBegin( const set_: ISet ); virtual; abstract;
314 procedure WriteSetEnd(); virtual; abstract;
315 procedure WriteBool( b: Boolean); virtual; abstract;
316 procedure WriteByte( b: ShortInt); virtual; abstract;
317 procedure WriteI16( i16: SmallInt); virtual; abstract;
318 procedure WriteI32( i32: Integer); virtual; abstract;
319 procedure WriteI64( const i64: Int64); virtual; abstract;
320 procedure WriteDouble( const d: Double); virtual; abstract;
321 procedure WriteString( const s: string ); virtual;
322 procedure WriteAnsiString( const s: AnsiString); virtual;
323 procedure WriteBinary( const b: TBytes); virtual; abstract;
324
325 function ReadMessageBegin: IMessage; virtual; abstract;
326 procedure ReadMessageEnd(); virtual; abstract;
327 function ReadStructBegin: IStruct; virtual; abstract;
328 procedure ReadStructEnd; virtual; abstract;
329 function ReadFieldBegin: IField; virtual; abstract;
330 procedure ReadFieldEnd(); virtual; abstract;
331 function ReadMapBegin: IMap; virtual; abstract;
332 procedure ReadMapEnd(); virtual; abstract;
333 function ReadListBegin: IList; virtual; abstract;
334 procedure ReadListEnd(); virtual; abstract;
335 function ReadSetBegin: ISet; virtual; abstract;
336 procedure ReadSetEnd(); virtual; abstract;
337 function ReadBool: Boolean; virtual; abstract;
338 function ReadByte: ShortInt; virtual; abstract;
339 function ReadI16: SmallInt; virtual; abstract;
340 function ReadI32: Integer; virtual; abstract;
341 function ReadI64: Int64; virtual; abstract;
342 function ReadDouble:Double; virtual; abstract;
343 function ReadBinary: TBytes; virtual; abstract;
344 function ReadString: string; virtual;
345 function ReadAnsiString: AnsiString; virtual;
346
347 property Transport: ITransport read GetTransport;
348
349 constructor Create( trans: ITransport );
350 end;
351
352 IBase = interface
353 ['{08D9BAA8-5EAA-410F-B50B-AC2E6E5E4155}']
354 function ToString: string;
355 procedure Read( const iprot: IProtocol);
356 procedure Write( const iprot: IProtocol);
357 end;
358
359 IStruct = interface
360 ['{5DCE39AA-C916-4BC7-A79B-96A0C36B2220}']
361 procedure SetName(const Value: string);
362 function GetName: string;
363 property Name: string read GetName write SetName;
364 end;
365
366 TStructImpl = class( TInterfacedObject, IStruct )
367 private
368 FName: string;
369 protected
370 function GetName: string;
371 procedure SetName(const Value: string);
372 public
373 constructor Create( const AName: string);
374 end;
375
376 TBinaryProtocolImpl = class( TProtocolImpl )
377 protected
378 const
379 VERSION_MASK : Cardinal = $ffff0000;
380 VERSION_1 : Cardinal = $80010000;
381 protected
382 FStrictRead : Boolean;
383 FStrictWrite : Boolean;
384
385 private
386 function ReadAll( var buf: TBytes; off: Integer; len: Integer ): Integer;
387 function ReadStringBody( size: Integer): string;
388
389 public
390
391 type
392 TFactory = class( TInterfacedObject, IProtocolFactory)
393 protected
394 FStrictRead : Boolean;
395 FStrictWrite : Boolean;
396 public
397 function GetProtocol( const trans: ITransport): IProtocol;
398 constructor Create( AStrictRead, AStrictWrite: Boolean ); overload;
399 constructor Create; overload;
400 end;
401
402 constructor Create( const trans: ITransport); overload;
403 constructor Create( const trans: ITransport; strictRead: Boolean; strictWrite: Boolean); overload;
404
405 procedure WriteMessageBegin( const msg: IMessage); override;
406 procedure WriteMessageEnd; override;
407 procedure WriteStructBegin( const struc: IStruct); override;
408 procedure WriteStructEnd; override;
409 procedure WriteFieldBegin( const field: IField); override;
410 procedure WriteFieldEnd; override;
411 procedure WriteFieldStop; override;
412 procedure WriteMapBegin( const map: IMap); override;
413 procedure WriteMapEnd; override;
414 procedure WriteListBegin( const list: IList); override;
415 procedure WriteListEnd(); override;
416 procedure WriteSetBegin( const set_: ISet ); override;
417 procedure WriteSetEnd(); override;
418 procedure WriteBool( b: Boolean); override;
419 procedure WriteByte( b: ShortInt); override;
420 procedure WriteI16( i16: SmallInt); override;
421 procedure WriteI32( i32: Integer); override;
422 procedure WriteI64( const i64: Int64); override;
423 procedure WriteDouble( const d: Double); override;
424 procedure WriteBinary( const b: TBytes); override;
425
426 function ReadMessageBegin: IMessage; override;
427 procedure ReadMessageEnd(); override;
428 function ReadStructBegin: IStruct; override;
429 procedure ReadStructEnd; override;
430 function ReadFieldBegin: IField; override;
431 procedure ReadFieldEnd(); override;
432 function ReadMapBegin: IMap; override;
433 procedure ReadMapEnd(); override;
434 function ReadListBegin: IList; override;
435 procedure ReadListEnd(); override;
436 function ReadSetBegin: ISet; override;
437 procedure ReadSetEnd(); override;
438 function ReadBool: Boolean; override;
439 function ReadByte: ShortInt; override;
440 function ReadI16: SmallInt; override;
441 function ReadI32: Integer; override;
442 function ReadI64: Int64; override;
443 function ReadDouble:Double; override;
444 function ReadBinary: TBytes; override;
445
446 end;
447
448
449 { TProtocolDecorator forwards all requests to an enclosed TProtocol instance,
450 providing a way to author concise concrete decorator subclasses. The decorator
451 does not (and should not) modify the behaviour of the enclosed TProtocol
452
453 See p.175 of Design Patterns (by Gamma et al.)
454 }
455 TProtocolDecorator = class( TProtocolImpl)
456 private
457 FWrappedProtocol : IProtocol;
458
459 public
460 // Encloses the specified protocol.
461 // All operations will be forward to the given protocol. Must be non-null.
462 constructor Create( const aProtocol : IProtocol);
463
464 procedure WriteMessageBegin( const msg: IMessage); override;
465 procedure WriteMessageEnd; override;
466 procedure WriteStructBegin( const struc: IStruct); override;
467 procedure WriteStructEnd; override;
468 procedure WriteFieldBegin( const field: IField); override;
469 procedure WriteFieldEnd; override;
470 procedure WriteFieldStop; override;
471 procedure WriteMapBegin( const map: IMap); override;
472 procedure WriteMapEnd; override;
473 procedure WriteListBegin( const list: IList); override;
474 procedure WriteListEnd(); override;
475 procedure WriteSetBegin( const set_: ISet ); override;
476 procedure WriteSetEnd(); override;
477 procedure WriteBool( b: Boolean); override;
478 procedure WriteByte( b: ShortInt); override;
479 procedure WriteI16( i16: SmallInt); override;
480 procedure WriteI32( i32: Integer); override;
481 procedure WriteI64( const i64: Int64); override;
482 procedure WriteDouble( const d: Double); override;
483 procedure WriteString( const s: string ); override;
484 procedure WriteAnsiString( const s: AnsiString); override;
485 procedure WriteBinary( const b: TBytes); override;
486
487 function ReadMessageBegin: IMessage; override;
488 procedure ReadMessageEnd(); override;
489 function ReadStructBegin: IStruct; override;
490 procedure ReadStructEnd; override;
491 function ReadFieldBegin: IField; override;
492 procedure ReadFieldEnd(); override;
493 function ReadMapBegin: IMap; override;
494 procedure ReadMapEnd(); override;
495 function ReadListBegin: IList; override;
496 procedure ReadListEnd(); override;
497 function ReadSetBegin: ISet; override;
498 procedure ReadSetEnd(); override;
499 function ReadBool: Boolean; override;
500 function ReadByte: ShortInt; override;
501 function ReadI16: SmallInt; override;
502 function ReadI32: Integer; override;
503 function ReadI64: Int64; override;
504 function ReadDouble:Double; override;
505 function ReadBinary: TBytes; override;
506 function ReadString: string; override;
507 function ReadAnsiString: AnsiString; override;
508 end;
509
510
511type
512 IRequestEvents = interface
Jens Geyer01640402013-09-25 21:12:21 +0200513 ['{F926A26A-5B00-4560-86FA-2CAE3BA73DAF}']
514 // Called before reading arguments.
515 procedure PreRead;
516 // Called between reading arguments and calling the handler.
517 procedure PostRead;
518 // Called between calling the handler and writing the response.
519 procedure PreWrite;
520 // Called after writing the response.
521 procedure PostWrite;
522 // Called when an oneway (async) function call completes successfully.
523 procedure OnewayComplete;
524 // Called if the handler throws an undeclared exception.
525 procedure UnhandledError( const e : Exception);
526 // Called when a client has finished request-handling to clean up
527 procedure CleanupContext;
528 end;
529
530
531 IProcessorEvents = interface
532 ['{A8661119-657C-447D-93C5-512E36162A45}']
533 // Called when a client is about to call the processor.
534 procedure Processing( const transport : ITransport);
535 // Called on any service function invocation
536 function CreateRequestContext( const aFunctionName : string) : IRequestEvents;
537 // Called when a client has finished request-handling to clean up
538 procedure CleanupContext;
539 end;
540
541
542 IProcessor = interface
543 ['{7BAE92A5-46DA-4F13-B6EA-0EABE233EE5F}']
Jens Geyerd430bbd2013-09-26 23:37:54 +0200544 function Process( const iprot :IProtocol; const oprot: IProtocol; const events : IProcessorEvents = nil): Boolean;
Jens Geyer01640402013-09-25 21:12:21 +0200545 end;
546
Jens Geyerd5436f52014-10-03 19:50:38 +0200547
548
549implementation
550
551function ConvertInt64ToDouble( const n: Int64): Double;
552begin
553 ASSERT( SizeOf(n) = SizeOf(Result));
554 System.Move( n, Result, SizeOf(Result));
555end;
556
557function ConvertDoubleToInt64( const d: Double): Int64;
558begin
559 ASSERT( SizeOf(d) = SizeOf(Result));
560 System.Move( d, Result, SizeOf(Result));
561end;
562
563{ TFieldImpl }
564
565constructor TFieldImpl.Create(const AName: string; const AType: TType;
566 AId: SmallInt);
567begin
568 inherited Create;
569 FName := AName;
570 FType := AType;
571 FId := AId;
572end;
573
574constructor TFieldImpl.Create;
575begin
576 inherited Create;
577 FName := '';
578 FType := Low(TType);
579 FId := 0;
580end;
581
582function TFieldImpl.GetId: SmallInt;
583begin
584 Result := FId;
585end;
586
587function TFieldImpl.GetName: string;
588begin
589 Result := FName;
590end;
591
592function TFieldImpl.GetType: TType;
593begin
594 Result := FType;
595end;
596
597procedure TFieldImpl.SetId(Value: SmallInt);
598begin
599 FId := Value;
600end;
601
602procedure TFieldImpl.SetName(const Value: string);
603begin
604 FName := Value;
605end;
606
607procedure TFieldImpl.SetType(Value: TType);
608begin
609 FType := Value;
610end;
611
612{ TProtocolImpl }
613
614constructor TProtocolImpl.Create(trans: ITransport);
615begin
616 inherited Create;
617 FTrans := trans;
618end;
619
620function TProtocolImpl.GetTransport: ITransport;
621begin
622 Result := FTrans;
623end;
624
625function TProtocolImpl.ReadAnsiString: AnsiString;
626var
627 b : TBytes;
628 len : Integer;
629begin
630 Result := '';
631 b := ReadBinary;
632 len := Length( b );
633 if len > 0 then
634 begin
635 SetLength( Result, len);
636 System.Move( b[0], Pointer(Result)^, len );
637 end;
638end;
639
640function TProtocolImpl.ReadString: string;
641begin
642 Result := TEncoding.UTF8.GetString( ReadBinary );
643end;
644
645procedure TProtocolImpl.WriteAnsiString(const s: AnsiString);
646var
647 b : TBytes;
648 len : Integer;
649begin
650 len := Length(s);
651 SetLength( b, len);
652 if len > 0 then
653 begin
654 System.Move( Pointer(s)^, b[0], len );
655 end;
656 WriteBinary( b );
657end;
658
659procedure TProtocolImpl.WriteString(const s: string);
660var
661 b : TBytes;
662begin
663 b := TEncoding.UTF8.GetBytes(s);
664 WriteBinary( b );
665end;
666
667{ TProtocolUtil }
668
669class procedure TProtocolUtil.Skip( prot: IProtocol; type_: TType);
670var field : IField;
671 map : IMap;
672 set_ : ISet;
673 list : IList;
674 i : Integer;
675begin
676 case type_ of
677 // simple types
678 TType.Bool_ : prot.ReadBool();
679 TType.Byte_ : prot.ReadByte();
680 TType.I16 : prot.ReadI16();
681 TType.I32 : prot.ReadI32();
682 TType.I64 : prot.ReadI64();
683 TType.Double_ : prot.ReadDouble();
684 TType.String_ : prot.ReadBinary();// Don't try to decode the string, just skip it.
685
686 // structured types
687 TType.Struct : begin
688 prot.ReadStructBegin();
689 while TRUE do begin
690 field := prot.ReadFieldBegin();
691 if (field.Type_ = TType.Stop) then Break;
692 Skip(prot, field.Type_);
693 prot.ReadFieldEnd();
694 end;
695 prot.ReadStructEnd();
696 end;
697
698 TType.Map : begin
699 map := prot.ReadMapBegin();
700 for i := 0 to map.Count-1 do begin
701 Skip(prot, map.KeyType);
702 Skip(prot, map.ValueType);
703 end;
704 prot.ReadMapEnd();
705 end;
706
707 TType.Set_ : begin
708 set_ := prot.ReadSetBegin();
709 for i := 0 to set_.Count-1
710 do Skip( prot, set_.ElementType);
711 prot.ReadSetEnd();
712 end;
713
714 TType.List : begin
715 list := prot.ReadListBegin();
716 for i := 0 to list.Count-1
717 do Skip( prot, list.ElementType);
718 prot.ReadListEnd();
719 end;
720
721 else
722 ASSERT( FALSE); // any new types?
723 end;
724end;
725
726{ TStructImpl }
727
728constructor TStructImpl.Create(const AName: string);
729begin
730 inherited Create;
731 FName := AName;
732end;
733
734function TStructImpl.GetName: string;
735begin
736 Result := FName;
737end;
738
739procedure TStructImpl.SetName(const Value: string);
740begin
741 FName := Value;
742end;
743
744{ TMapImpl }
745
Jens Geyer96eff172015-03-02 01:30:05 +0100746constructor TMapImpl.Create( AKeyType, AValueType: TType; ACount: Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +0200747begin
748 inherited Create;
749 FValueType := AValueType;
750 FKeyType := AKeyType;
751 FCount := ACount;
752end;
753
754constructor TMapImpl.Create;
755begin
756 inherited Create;
757end;
758
759function TMapImpl.GetCount: Integer;
760begin
761 Result := FCount;
762end;
763
764function TMapImpl.GetKeyType: TType;
765begin
766 Result := FKeyType;
767end;
768
769function TMapImpl.GetValueType: TType;
770begin
771 Result := FValueType;
772end;
773
774procedure TMapImpl.SetCount(Value: Integer);
775begin
776 FCount := Value;
777end;
778
779procedure TMapImpl.SetKeyType(Value: TType);
780begin
781 FKeyType := Value;
782end;
783
784procedure TMapImpl.SetValueType(Value: TType);
785begin
786 FValueType := Value;
787end;
788
789{ IMessage }
790
791constructor TMessageImpl.Create(AName: string; AMessageType: TMessageType;
792 ASeqID: Integer);
793begin
794 inherited Create;
795 FName := AName;
796 FMessageType := AMessageType;
797 FSeqID := ASeqID;
798end;
799
800constructor TMessageImpl.Create;
801begin
802 inherited;
803end;
804
805function TMessageImpl.GetName: string;
806begin
807 Result := FName;
808end;
809
810function TMessageImpl.GetSeqID: Integer;
811begin
812 Result := FSeqID;
813end;
814
815function TMessageImpl.GetType: TMessageType;
816begin
817 Result := FMessageType;
818end;
819
820procedure TMessageImpl.SetName(const Value: string);
821begin
822 FName := Value;
823end;
824
825procedure TMessageImpl.SetSeqID(Value: Integer);
826begin
827 FSeqID := Value;
828end;
829
830procedure TMessageImpl.SetType(Value: TMessageType);
831begin
832 FMessageType := Value;
833end;
834
835{ ISet }
836
837constructor TSetImpl.Create( AElementType: TType; ACount: Integer);
838begin
839 inherited Create;
840 FCount := ACount;
841 FElementType := AElementType;
842end;
843
844constructor TSetImpl.Create;
845begin
846 inherited Create;
847end;
848
849function TSetImpl.GetCount: Integer;
850begin
851 Result := FCount;
852end;
853
854function TSetImpl.GetElementType: TType;
855begin
856 Result := FElementType;
857end;
858
859procedure TSetImpl.SetCount(Value: Integer);
860begin
861 FCount := Value;
862end;
863
864procedure TSetImpl.SetElementType(Value: TType);
865begin
866 FElementType := Value;
867end;
868
869{ IList }
870
871constructor TListImpl.Create( AElementType: TType; ACount: Integer);
872begin
873 inherited Create;
874 FCount := ACount;
875 FElementType := AElementType;
876end;
877
878constructor TListImpl.Create;
879begin
880 inherited Create;
881end;
882
883function TListImpl.GetCount: Integer;
884begin
885 Result := FCount;
886end;
887
888function TListImpl.GetElementType: TType;
889begin
890 Result := FElementType;
891end;
892
893procedure TListImpl.SetCount(Value: Integer);
894begin
895 FCount := Value;
896end;
897
898procedure TListImpl.SetElementType(Value: TType);
899begin
900 FElementType := Value;
901end;
902
903{ TBinaryProtocolImpl }
904
905constructor TBinaryProtocolImpl.Create( const trans: ITransport);
906begin
907 //no inherited
908 Create( trans, False, True);
909end;
910
911constructor TBinaryProtocolImpl.Create( const trans: ITransport; strictRead,
912 strictWrite: Boolean);
913begin
914 inherited Create( trans );
915 FStrictRead := strictRead;
916 FStrictWrite := strictWrite;
917end;
918
919function TBinaryProtocolImpl.ReadAll( var buf: TBytes; off,
920 len: Integer): Integer;
921begin
922 Result := FTrans.ReadAll( buf, off, len );
923end;
924
925function TBinaryProtocolImpl.ReadBinary: TBytes;
926var
927 size : Integer;
928 buf : TBytes;
929begin
930 size := ReadI32;
931 SetLength( buf, size );
932 FTrans.ReadAll( buf, 0, size);
933 Result := buf;
934end;
935
936function TBinaryProtocolImpl.ReadBool: Boolean;
937begin
938 Result := ReadByte = 1;
939end;
940
941function TBinaryProtocolImpl.ReadByte: ShortInt;
942var
943 bin : TBytes;
944begin
945 SetLength( bin, 1);
946 ReadAll( bin, 0, 1 );
947 Result := ShortInt( bin[0]);
948end;
949
950function TBinaryProtocolImpl.ReadDouble: Double;
951begin
952 Result := ConvertInt64ToDouble( ReadI64 )
953end;
954
955function TBinaryProtocolImpl.ReadFieldBegin: IField;
956var
957 field : IField;
958begin
959 field := TFieldImpl.Create;
960 field.Type_ := TType( ReadByte);
961 if ( field.Type_ <> TType.Stop ) then
962 begin
963 field.Id := ReadI16;
964 end;
965 Result := field;
966end;
967
968procedure TBinaryProtocolImpl.ReadFieldEnd;
969begin
970
971end;
972
973function TBinaryProtocolImpl.ReadI16: SmallInt;
974var
975 i16in : TBytes;
976begin
977 SetLength( i16in, 2 );
978 ReadAll( i16in, 0, 2);
979 Result := SmallInt(((i16in[0] and $FF) shl 8) or (i16in[1] and $FF));
980end;
981
982function TBinaryProtocolImpl.ReadI32: Integer;
983var
984 i32in : TBytes;
985begin
986 SetLength( i32in, 4 );
987 ReadAll( i32in, 0, 4);
988
989 Result := Integer(
990 ((i32in[0] and $FF) shl 24) or
991 ((i32in[1] and $FF) shl 16) or
992 ((i32in[2] and $FF) shl 8) or
993 (i32in[3] and $FF));
994
995end;
996
997function TBinaryProtocolImpl.ReadI64: Int64;
998var
999 i64in : TBytes;
1000begin
1001 SetLength( i64in, 8);
1002 ReadAll( i64in, 0, 8);
1003 Result :=
1004 (Int64( i64in[0] and $FF) shl 56) or
1005 (Int64( i64in[1] and $FF) shl 48) or
1006 (Int64( i64in[2] and $FF) shl 40) or
1007 (Int64( i64in[3] and $FF) shl 32) or
1008 (Int64( i64in[4] and $FF) shl 24) or
1009 (Int64( i64in[5] and $FF) shl 16) or
1010 (Int64( i64in[6] and $FF) shl 8) or
1011 (Int64( i64in[7] and $FF));
1012end;
1013
1014function TBinaryProtocolImpl.ReadListBegin: IList;
1015var
1016 list : IList;
1017begin
1018 list := TListImpl.Create;
1019 list.ElementType := TType( ReadByte );
1020 list.Count := ReadI32;
1021 Result := list;
1022end;
1023
1024procedure TBinaryProtocolImpl.ReadListEnd;
1025begin
1026
1027end;
1028
1029function TBinaryProtocolImpl.ReadMapBegin: IMap;
1030var
1031 map : IMap;
1032begin
1033 map := TMapImpl.Create;
1034 map.KeyType := TType( ReadByte );
1035 map.ValueType := TType( ReadByte );
1036 map.Count := ReadI32;
1037 Result := map;
1038end;
1039
1040procedure TBinaryProtocolImpl.ReadMapEnd;
1041begin
1042
1043end;
1044
1045function TBinaryProtocolImpl.ReadMessageBegin: IMessage;
1046var
1047 size : Integer;
1048 version : Integer;
1049 message : IMessage;
1050begin
1051 message := TMessageImpl.Create;
1052 size := ReadI32;
1053 if (size < 0) then
1054 begin
1055 version := size and Integer( VERSION_MASK);
1056 if ( version <> Integer( VERSION_1)) then
1057 begin
1058 raise TProtocolException.Create(TProtocolException.BAD_VERSION, 'Bad version in ReadMessageBegin: ' + IntToStr(version) );
1059 end;
1060 message.Type_ := TMessageType( size and $000000ff);
1061 message.Name := ReadString;
1062 message.SeqID := ReadI32;
1063 end else
1064 begin
1065 if FStrictRead then
1066 begin
1067 raise TProtocolException.Create( TProtocolException.BAD_VERSION, 'Missing version in readMessageBegin, old client?' );
1068 end;
1069 message.Name := ReadStringBody( size );
1070 message.Type_ := TMessageType( ReadByte );
1071 message.SeqID := ReadI32;
1072 end;
1073 Result := message;
1074end;
1075
1076procedure TBinaryProtocolImpl.ReadMessageEnd;
1077begin
1078 inherited;
1079
1080end;
1081
1082function TBinaryProtocolImpl.ReadSetBegin: ISet;
1083var
1084 set_ : ISet;
1085begin
1086 set_ := TSetImpl.Create;
1087 set_.ElementType := TType( ReadByte );
1088 set_.Count := ReadI32;
1089 Result := set_;
1090end;
1091
1092procedure TBinaryProtocolImpl.ReadSetEnd;
1093begin
1094
1095end;
1096
1097function TBinaryProtocolImpl.ReadStringBody( size: Integer): string;
1098var
1099 buf : TBytes;
1100begin
1101 SetLength( buf, size );
1102 FTrans.ReadAll( buf, 0, size );
1103 Result := TEncoding.UTF8.GetString( buf);
1104end;
1105
1106function TBinaryProtocolImpl.ReadStructBegin: IStruct;
1107begin
1108 Result := TStructImpl.Create('');
1109end;
1110
1111procedure TBinaryProtocolImpl.ReadStructEnd;
1112begin
1113 inherited;
1114
1115end;
1116
1117procedure TBinaryProtocolImpl.WriteBinary( const b: TBytes);
1118var iLen : Integer;
1119begin
1120 iLen := Length(b);
1121 WriteI32( iLen);
1122 if iLen > 0 then FTrans.Write(b, 0, iLen);
1123end;
1124
1125procedure TBinaryProtocolImpl.WriteBool(b: Boolean);
1126begin
1127 if b then
1128 begin
1129 WriteByte( 1 );
1130 end else
1131 begin
1132 WriteByte( 0 );
1133 end;
1134end;
1135
1136procedure TBinaryProtocolImpl.WriteByte(b: ShortInt);
1137var
1138 a : TBytes;
1139begin
1140 SetLength( a, 1);
1141 a[0] := Byte( b );
1142 FTrans.Write( a, 0, 1 );
1143end;
1144
1145procedure TBinaryProtocolImpl.WriteDouble( const d: Double);
1146begin
1147 WriteI64(ConvertDoubleToInt64(d));
1148end;
1149
1150procedure TBinaryProtocolImpl.WriteFieldBegin( const field: IField);
1151begin
1152 WriteByte(ShortInt(field.Type_));
1153 WriteI16(field.ID);
1154end;
1155
1156procedure TBinaryProtocolImpl.WriteFieldEnd;
1157begin
1158
1159end;
1160
1161procedure TBinaryProtocolImpl.WriteFieldStop;
1162begin
1163 WriteByte(ShortInt(TType.Stop));
1164end;
1165
1166procedure TBinaryProtocolImpl.WriteI16(i16: SmallInt);
1167var
1168 i16out : TBytes;
1169begin
1170 SetLength( i16out, 2);
1171 i16out[0] := Byte($FF and (i16 shr 8));
1172 i16out[1] := Byte($FF and i16);
1173 FTrans.Write( i16out );
1174end;
1175
1176procedure TBinaryProtocolImpl.WriteI32(i32: Integer);
1177var
1178 i32out : TBytes;
1179begin
1180 SetLength( i32out, 4);
1181 i32out[0] := Byte($FF and (i32 shr 24));
1182 i32out[1] := Byte($FF and (i32 shr 16));
1183 i32out[2] := Byte($FF and (i32 shr 8));
1184 i32out[3] := Byte($FF and i32);
1185 FTrans.Write( i32out, 0, 4);
1186end;
1187
1188procedure TBinaryProtocolImpl.WriteI64( const i64: Int64);
1189var
1190 i64out : TBytes;
1191begin
1192 SetLength( i64out, 8);
1193 i64out[0] := Byte($FF and (i64 shr 56));
1194 i64out[1] := Byte($FF and (i64 shr 48));
1195 i64out[2] := Byte($FF and (i64 shr 40));
1196 i64out[3] := Byte($FF and (i64 shr 32));
1197 i64out[4] := Byte($FF and (i64 shr 24));
1198 i64out[5] := Byte($FF and (i64 shr 16));
1199 i64out[6] := Byte($FF and (i64 shr 8));
1200 i64out[7] := Byte($FF and i64);
1201 FTrans.Write( i64out, 0, 8);
1202end;
1203
1204procedure TBinaryProtocolImpl.WriteListBegin( const list: IList);
1205begin
1206 WriteByte(ShortInt(list.ElementType));
1207 WriteI32(list.Count);
1208end;
1209
1210procedure TBinaryProtocolImpl.WriteListEnd;
1211begin
1212
1213end;
1214
1215procedure TBinaryProtocolImpl.WriteMapBegin( const map: IMap);
1216begin
1217 WriteByte(ShortInt(map.KeyType));
1218 WriteByte(ShortInt(map.ValueType));
1219 WriteI32(map.Count);
1220end;
1221
1222procedure TBinaryProtocolImpl.WriteMapEnd;
1223begin
1224
1225end;
1226
1227procedure TBinaryProtocolImpl.WriteMessageBegin( const msg: IMessage);
1228var
1229 version : Cardinal;
1230begin
1231 if FStrictWrite then
1232 begin
1233 version := VERSION_1 or Cardinal( msg.Type_);
1234 WriteI32( Integer( version) );
1235 WriteString( msg.Name);
1236 WriteI32( msg.SeqID);
1237 end else
1238 begin
1239 WriteString( msg.Name);
1240 WriteByte(ShortInt( msg.Type_));
1241 WriteI32( msg.SeqID);
1242 end;
1243end;
1244
1245procedure TBinaryProtocolImpl.WriteMessageEnd;
1246begin
1247
1248end;
1249
1250procedure TBinaryProtocolImpl.WriteSetBegin( const set_: ISet);
1251begin
1252 WriteByte(ShortInt(set_.ElementType));
1253 WriteI32(set_.Count);
1254end;
1255
1256procedure TBinaryProtocolImpl.WriteSetEnd;
1257begin
1258
1259end;
1260
1261procedure TBinaryProtocolImpl.WriteStructBegin( const struc: IStruct);
1262begin
1263
1264end;
1265
1266procedure TBinaryProtocolImpl.WriteStructEnd;
1267begin
1268
1269end;
1270
1271{ TProtocolException }
1272
1273constructor TProtocolException.Create;
1274begin
1275 inherited Create('');
1276 FType := UNKNOWN;
1277end;
1278
1279constructor TProtocolException.Create(type_: Integer);
1280begin
1281 inherited Create('');
1282 FType := type_;
1283end;
1284
1285constructor TProtocolException.Create(type_: Integer; const msg: string);
1286begin
1287 inherited Create( msg );
1288 FType := type_;
1289end;
1290
1291{ TThriftStringBuilder }
1292
1293function TThriftStringBuilder.Append(const Value: TBytes): TStringBuilder;
1294begin
1295 Result := Append( string( RawByteString(Value)) );
1296end;
1297
1298function TThriftStringBuilder.Append(
1299 const Value: IThriftContainer): TStringBuilder;
1300begin
1301 Result := Append( Value.ToString );
1302end;
1303
1304{ TBinaryProtocolImpl.TFactory }
1305
1306constructor TBinaryProtocolImpl.TFactory.Create(AStrictRead, AStrictWrite: Boolean);
1307begin
1308 inherited Create;
1309 FStrictRead := AStrictRead;
1310 FStrictWrite := AStrictWrite;
1311end;
1312
1313constructor TBinaryProtocolImpl.TFactory.Create;
1314begin
1315 //no inherited;
1316 Create( False, True )
1317end;
1318
1319function TBinaryProtocolImpl.TFactory.GetProtocol( const trans: ITransport): IProtocol;
1320begin
1321 Result := TBinaryProtocolImpl.Create( trans, FStrictRead, FStrictWrite);
1322end;
1323
1324
1325{ TProtocolDecorator }
1326
1327constructor TProtocolDecorator.Create( const aProtocol : IProtocol);
1328begin
1329 ASSERT( aProtocol <> nil);
1330 inherited Create( aProtocol.Transport);
1331 FWrappedProtocol := aProtocol;
1332end;
1333
1334
1335procedure TProtocolDecorator.WriteMessageBegin( const msg: IMessage);
1336begin
1337 FWrappedProtocol.WriteMessageBegin( msg);
1338end;
1339
1340
1341procedure TProtocolDecorator.WriteMessageEnd;
1342begin
1343 FWrappedProtocol.WriteMessageEnd;
1344end;
1345
1346
1347procedure TProtocolDecorator.WriteStructBegin( const struc: IStruct);
1348begin
1349 FWrappedProtocol.WriteStructBegin( struc);
1350end;
1351
1352
1353procedure TProtocolDecorator.WriteStructEnd;
1354begin
1355 FWrappedProtocol.WriteStructEnd;
1356end;
1357
1358
1359procedure TProtocolDecorator.WriteFieldBegin( const field: IField);
1360begin
1361 FWrappedProtocol.WriteFieldBegin( field);
1362end;
1363
1364
1365procedure TProtocolDecorator.WriteFieldEnd;
1366begin
1367 FWrappedProtocol.WriteFieldEnd;
1368end;
1369
1370
1371procedure TProtocolDecorator.WriteFieldStop;
1372begin
1373 FWrappedProtocol.WriteFieldStop;
1374end;
1375
1376
1377procedure TProtocolDecorator.WriteMapBegin( const map: IMap);
1378begin
1379 FWrappedProtocol.WriteMapBegin( map);
1380end;
1381
1382
1383procedure TProtocolDecorator.WriteMapEnd;
1384begin
1385 FWrappedProtocol.WriteMapEnd;
1386end;
1387
1388
1389procedure TProtocolDecorator.WriteListBegin( const list: IList);
1390begin
1391 FWrappedProtocol.WriteListBegin( list);
1392end;
1393
1394
1395procedure TProtocolDecorator.WriteListEnd();
1396begin
1397 FWrappedProtocol.WriteListEnd();
1398end;
1399
1400
1401procedure TProtocolDecorator.WriteSetBegin( const set_: ISet );
1402begin
1403 FWrappedProtocol.WriteSetBegin( set_);
1404end;
1405
1406
1407procedure TProtocolDecorator.WriteSetEnd();
1408begin
1409 FWrappedProtocol.WriteSetEnd();
1410end;
1411
1412
1413procedure TProtocolDecorator.WriteBool( b: Boolean);
1414begin
1415 FWrappedProtocol.WriteBool( b);
1416end;
1417
1418
1419procedure TProtocolDecorator.WriteByte( b: ShortInt);
1420begin
1421 FWrappedProtocol.WriteByte( b);
1422end;
1423
1424
1425procedure TProtocolDecorator.WriteI16( i16: SmallInt);
1426begin
1427 FWrappedProtocol.WriteI16( i16);
1428end;
1429
1430
1431procedure TProtocolDecorator.WriteI32( i32: Integer);
1432begin
1433 FWrappedProtocol.WriteI32( i32);
1434end;
1435
1436
1437procedure TProtocolDecorator.WriteI64( const i64: Int64);
1438begin
1439 FWrappedProtocol.WriteI64( i64);
1440end;
1441
1442
1443procedure TProtocolDecorator.WriteDouble( const d: Double);
1444begin
1445 FWrappedProtocol.WriteDouble( d);
1446end;
1447
1448
1449procedure TProtocolDecorator.WriteString( const s: string );
1450begin
1451 FWrappedProtocol.WriteString( s);
1452end;
1453
1454
1455procedure TProtocolDecorator.WriteAnsiString( const s: AnsiString);
1456begin
1457 FWrappedProtocol.WriteAnsiString( s);
1458end;
1459
1460
1461procedure TProtocolDecorator.WriteBinary( const b: TBytes);
1462begin
1463 FWrappedProtocol.WriteBinary( b);
1464end;
1465
1466
1467function TProtocolDecorator.ReadMessageBegin: IMessage;
1468begin
1469 result := FWrappedProtocol.ReadMessageBegin;
1470end;
1471
1472
1473procedure TProtocolDecorator.ReadMessageEnd();
1474begin
1475 FWrappedProtocol.ReadMessageEnd();
1476end;
1477
1478
1479function TProtocolDecorator.ReadStructBegin: IStruct;
1480begin
1481 result := FWrappedProtocol.ReadStructBegin;
1482end;
1483
1484
1485procedure TProtocolDecorator.ReadStructEnd;
1486begin
1487 FWrappedProtocol.ReadStructEnd;
1488end;
1489
1490
1491function TProtocolDecorator.ReadFieldBegin: IField;
1492begin
1493 result := FWrappedProtocol.ReadFieldBegin;
1494end;
1495
1496
1497procedure TProtocolDecorator.ReadFieldEnd();
1498begin
1499 FWrappedProtocol.ReadFieldEnd();
1500end;
1501
1502
1503function TProtocolDecorator.ReadMapBegin: IMap;
1504begin
1505 result := FWrappedProtocol.ReadMapBegin;
1506end;
1507
1508
1509procedure TProtocolDecorator.ReadMapEnd();
1510begin
1511 FWrappedProtocol.ReadMapEnd();
1512end;
1513
1514
1515function TProtocolDecorator.ReadListBegin: IList;
1516begin
1517 result := FWrappedProtocol.ReadListBegin;
1518end;
1519
1520
1521procedure TProtocolDecorator.ReadListEnd();
1522begin
1523 FWrappedProtocol.ReadListEnd();
1524end;
1525
1526
1527function TProtocolDecorator.ReadSetBegin: ISet;
1528begin
1529 result := FWrappedProtocol.ReadSetBegin;
1530end;
1531
1532
1533procedure TProtocolDecorator.ReadSetEnd();
1534begin
1535 FWrappedProtocol.ReadSetEnd();
1536end;
1537
1538
1539function TProtocolDecorator.ReadBool: Boolean;
1540begin
1541 result := FWrappedProtocol.ReadBool;
1542end;
1543
1544
1545function TProtocolDecorator.ReadByte: ShortInt;
1546begin
1547 result := FWrappedProtocol.ReadByte;
1548end;
1549
1550
1551function TProtocolDecorator.ReadI16: SmallInt;
1552begin
1553 result := FWrappedProtocol.ReadI16;
1554end;
1555
1556
1557function TProtocolDecorator.ReadI32: Integer;
1558begin
1559 result := FWrappedProtocol.ReadI32;
1560end;
1561
1562
1563function TProtocolDecorator.ReadI64: Int64;
1564begin
1565 result := FWrappedProtocol.ReadI64;
1566end;
1567
1568
1569function TProtocolDecorator.ReadDouble:Double;
1570begin
1571 result := FWrappedProtocol.ReadDouble;
1572end;
1573
1574
1575function TProtocolDecorator.ReadBinary: TBytes;
1576begin
1577 result := FWrappedProtocol.ReadBinary;
1578end;
1579
1580
1581function TProtocolDecorator.ReadString: string;
1582begin
1583 result := FWrappedProtocol.ReadString;
1584end;
1585
1586
1587function TProtocolDecorator.ReadAnsiString: AnsiString;
1588begin
1589 result := FWrappedProtocol.ReadAnsiString;
1590end;
1591
1592
1593
1594end.
1595