blob: c354a37daccfe339fb4a14b1bc4564e84cd466b9 [file] [log] [blame]
Roger Meier2b2c0b22012-09-12 20:09:02 +00001(*
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 *)
19unit Thrift.Serializer;
20
Jens Geyer9f7f11e2016-04-14 21:37:11 +020021{$I Thrift.Defines.inc}
Nick4f5229e2016-04-14 16:43:22 +030022
Roger Meier2b2c0b22012-09-12 20:09:02 +000023interface
24
25uses
Jens Geyer9f7f11e2016-04-14 21:37:11 +020026 {$IFDEF OLD_UNIT_NAMES}
27 Classes, Windows, SysUtils,
Nick4f5229e2016-04-14 16:43:22 +030028 {$ELSE}
Jens Geyer9f7f11e2016-04-14 21:37:11 +020029 System.Classes, Winapi.Windows, System.SysUtils,
30 {$ENDIF}
Jens Geyera019cda2019-11-09 23:24:52 +010031 Thrift.Configuration,
Roger Meier2b2c0b22012-09-12 20:09:02 +000032 Thrift.Protocol,
33 Thrift.Transport,
34 Thrift.Stream;
35
36
37type
38 // Generic utility for easily serializing objects into a byte array or Stream.
39 TSerializer = class
Jens Geyerfad7fd32019-11-09 23:24:52 +010040 strict private
Jens Geyerf726ae32021-06-04 11:17:26 +020041 FStream : TThriftMemoryStream;
Roger Meier2b2c0b22012-09-12 20:09:02 +000042 FTransport : ITransport;
43 FProtocol : IProtocol;
44
45 public
Jens Geyera019cda2019-11-09 23:24:52 +010046 constructor Create( const aProtFact : IProtocolFactory = nil; // defaults to TBinaryProtocol
47 const aTransFact : ITransportFactory = nil;
48 const aConfig : IThriftConfiguration = nil);
Jens Geyered994552019-11-09 23:24:52 +010049
Roger Meier2b2c0b22012-09-12 20:09:02 +000050 // DTOR
51 destructor Destroy; override;
52
53 // Serialize the Thrift object.
54 function Serialize( const input : IBase) : TBytes; overload;
55 procedure Serialize( const input : IBase; const aStm : TStream); overload;
56 end;
57
58
59 // Generic utility for easily deserializing objects from byte array or Stream.
60 TDeserializer = class
Jens Geyerfad7fd32019-11-09 23:24:52 +010061 strict private
Jens Geyerf726ae32021-06-04 11:17:26 +020062 FStream : TThriftMemoryStream;
Roger Meier2b2c0b22012-09-12 20:09:02 +000063 FTransport : ITransport;
64 FProtocol : IProtocol;
65
66 public
Jens Geyera019cda2019-11-09 23:24:52 +010067 constructor Create( const aProtFact : IProtocolFactory = nil; // defaults to TBinaryProtocol
68 const aTransFact : ITransportFactory = nil;
Jens Geyer3e6be732025-06-04 22:31:55 +020069 const aConfig : IThriftConfiguration = nil);
Jens Geyered994552019-11-09 23:24:52 +010070
Roger Meier2b2c0b22012-09-12 20:09:02 +000071 // DTOR
72 destructor Destroy; override;
73
74 // Deserialize the Thrift object data.
75 procedure Deserialize( const input : TBytes; const target : IBase); overload;
76 procedure Deserialize( const input : TStream; const target : IBase); overload;
Jens Geyer3e6be732025-06-04 22:31:55 +020077
78 // helper
79 property Protocol : IProtocol read FProtocol;
80 property Transport : ITransport read FTransport;
81 property Stream : TThriftMemoryStream read FStream;
Roger Meier2b2c0b22012-09-12 20:09:02 +000082 end;
83
84
85
86implementation
87
88
89{ TSerializer }
90
91
Jens Geyera019cda2019-11-09 23:24:52 +010092constructor TSerializer.Create( const aProtFact : IProtocolFactory;
93 const aTransFact : ITransportFactory;
94 const aConfig : IThriftConfiguration);
Roger Meier2b2c0b22012-09-12 20:09:02 +000095var adapter : IThriftStream;
Jens Geyera019cda2019-11-09 23:24:52 +010096 protfact : IProtocolFactory;
Roger Meier2b2c0b22012-09-12 20:09:02 +000097begin
98 inherited Create;
Jens Geyera019cda2019-11-09 23:24:52 +010099
Jens Geyerf726ae32021-06-04 11:17:26 +0200100 FStream := TThriftMemoryStream.Create;
Roger Meier2b2c0b22012-09-12 20:09:02 +0000101 adapter := TThriftStreamAdapterDelphi.Create( FStream, FALSE);
Jens Geyera019cda2019-11-09 23:24:52 +0100102
103 FTransport := TStreamTransportImpl.Create( nil, adapter, aConfig);
104 if aTransfact <> nil then FTransport := aTransfact.GetTransport( FTransport);
105
106 if aProtFact <> nil
107 then protfact := aProtFact
108 else protfact := TBinaryProtocolImpl.TFactory.Create;
109 FProtocol := protfact.GetProtocol( FTransport);
Jens Geyered994552019-11-09 23:24:52 +0100110
111 if not FTransport.IsOpen
112 then FTransport.Open;
Roger Meier2b2c0b22012-09-12 20:09:02 +0000113end;
114
115
116destructor TSerializer.Destroy;
117begin
118 try
119 FProtocol := nil;
120 FTransport := nil;
121 FreeAndNil( FStream);
122 finally
123 inherited Destroy;
124 end;
125end;
126
127
128function TSerializer.Serialize( const input : IBase) : TBytes;
129// Serialize the Thrift object into a byte array. The process is simple,
130// just clear the byte array output, write the object into it, and grab the
131// raw bytes.
132var iBytes : Int64;
133begin
134 try
135 FStream.Size := 0;
136 input.Write( FProtocol);
Jens Geyered994552019-11-09 23:24:52 +0100137 FTransport.Flush;
138
Roger Meier2b2c0b22012-09-12 20:09:02 +0000139 SetLength( result, FStream.Size);
140 iBytes := Length(result);
141 if iBytes > 0
142 then Move( FStream.Memory^, result[0], iBytes);
143 finally
144 FStream.Size := 0; // free any allocated memory
145 end;
146end;
147
148
149procedure TSerializer.Serialize( const input : IBase; const aStm : TStream);
150// Serialize the Thrift object into a byte array. The process is simple,
151// just clear the byte array output, write the object into it, and grab the
Jens Geyerd5436f52014-10-03 19:50:38 +0200152// raw bytes.
Roger Meier2b2c0b22012-09-12 20:09:02 +0000153const COPY_ENTIRE_STREAM = 0;
154begin
155 try
156 FStream.Size := 0;
157 input.Write( FProtocol);
Jens Geyered994552019-11-09 23:24:52 +0100158 FTransport.Flush;
159
Roger Meier2b2c0b22012-09-12 20:09:02 +0000160 aStm.CopyFrom( FStream, COPY_ENTIRE_STREAM);
161 finally
162 FStream.Size := 0; // free any allocated memory
163 end;
164end;
165
166
167{ TDeserializer }
168
169
Jens Geyera019cda2019-11-09 23:24:52 +0100170constructor TDeserializer.Create( const aProtFact : IProtocolFactory;
171 const aTransFact : ITransportFactory;
Jens Geyer3e6be732025-06-04 22:31:55 +0200172 const aConfig : IThriftConfiguration);
Roger Meier2b2c0b22012-09-12 20:09:02 +0000173var adapter : IThriftStream;
Jens Geyera019cda2019-11-09 23:24:52 +0100174 protfact : IProtocolFactory;
Roger Meier2b2c0b22012-09-12 20:09:02 +0000175begin
176 inherited Create;
Jens Geyera019cda2019-11-09 23:24:52 +0100177
Jens Geyer3e6be732025-06-04 22:31:55 +0200178 FStream := TThriftMemoryStream.Create;
179 adapter := TThriftStreamAdapterDelphi.Create( FStream, FALSE);
Jens Geyera019cda2019-11-09 23:24:52 +0100180
181 FTransport := TStreamTransportImpl.Create( adapter, nil, aConfig);
182 if aTransfact <> nil then FTransport := aTransfact.GetTransport( FTransport);
183
184 if aProtFact <> nil
185 then protfact := aProtFact
186 else protfact := TBinaryProtocolImpl.TFactory.Create;
187 FProtocol := protfact.GetProtocol( FTransport);
Jens Geyered994552019-11-09 23:24:52 +0100188
189 if not FTransport.IsOpen
190 then FTransport.Open;
Roger Meier2b2c0b22012-09-12 20:09:02 +0000191end;
192
193
194destructor TDeserializer.Destroy;
195begin
196 try
197 FProtocol := nil;
198 FTransport := nil;
199 FreeAndNil( FStream);
200 finally
201 inherited Destroy;
202 end;
203end;
204
205
206procedure TDeserializer.Deserialize( const input : TBytes; const target : IBase);
207// Deserialize the Thrift object data from the byte array.
208var iBytes : Int64;
209begin
210 try
211 iBytes := Length(input);
212 FStream.Size := iBytes;
Jens Geyer3e6be732025-06-04 22:31:55 +0200213 if iBytes > 0 then begin
214 Move( input[0], FStream.Memory^, iBytes);
215 Transport.ResetMessageSizeAndConsumedBytes(); // size has changed
216 Transport.UpdateKnownMessageSize(iBytes);
217 end;
Roger Meier2b2c0b22012-09-12 20:09:02 +0000218
219 target.Read( FProtocol);
220 finally
221 FStream.Size := 0; // free any allocated memory
222 end;
223end;
224
225
226procedure TDeserializer.Deserialize( const input : TStream; const target : IBase);
227// Deserialize the Thrift object data from the byte array.
228const COPY_ENTIRE_STREAM = 0;
229var before : Int64;
230begin
231 try
Jens Geyer3e6be732025-06-04 22:31:55 +0200232 if Assigned(input) then begin
233 before := FStream.Position;
234 ASSERT( before = 0);
235 FStream.CopyFrom( input, COPY_ENTIRE_STREAM);
236 FStream.Position := before;
237 Transport.ResetMessageSizeAndConsumedBytes(); // size has changed
238 Transport.UpdateKnownMessageSize(FStream.Size);
239 end;
240
Roger Meier2b2c0b22012-09-12 20:09:02 +0000241 target.Read( FProtocol);
242 finally
243 FStream.Size := 0; // free any allocated memory
244 end;
245end;
246
247
248end.
249