Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 23 additions & 9 deletions lib/delphi/src/Thrift.Serializer.pas
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,19 @@ TDeserializer = class
public
constructor Create( const aProtFact : IProtocolFactory = nil; // defaults to TBinaryProtocol
const aTransFact : ITransportFactory = nil;
const aConfig : IThriftConfiguration = nil);
const aConfig : IThriftConfiguration = nil);

// DTOR
destructor Destroy; override;

// Deserialize the Thrift object data.
procedure Deserialize( const input : TBytes; const target : IBase); overload;
procedure Deserialize( const input : TStream; const target : IBase); overload;

// helper
property Protocol : IProtocol read FProtocol;
property Transport : ITransport read FTransport;
property Stream : TThriftMemoryStream read FStream;
end;


Expand Down Expand Up @@ -164,14 +169,14 @@ procedure TSerializer.Serialize( const input : IBase; const aStm : TStream);

constructor TDeserializer.Create( const aProtFact : IProtocolFactory;
const aTransFact : ITransportFactory;
const aConfig : IThriftConfiguration);
const aConfig : IThriftConfiguration);
var adapter : IThriftStream;
protfact : IProtocolFactory;
begin
inherited Create;

FStream := TThriftMemoryStream.Create;
adapter := TThriftStreamAdapterDelphi.Create( FStream, FALSE);
FStream := TThriftMemoryStream.Create;
adapter := TThriftStreamAdapterDelphi.Create( FStream, FALSE);

FTransport := TStreamTransportImpl.Create( adapter, nil, aConfig);
if aTransfact <> nil then FTransport := aTransfact.GetTransport( FTransport);
Expand Down Expand Up @@ -205,8 +210,11 @@ procedure TDeserializer.Deserialize( const input : TBytes; const target : IBase)
try
iBytes := Length(input);
FStream.Size := iBytes;
if iBytes > 0
then Move( input[0], FStream.Memory^, iBytes);
if iBytes > 0 then begin
Move( input[0], FStream.Memory^, iBytes);
Transport.ResetMessageSizeAndConsumedBytes(); // size has changed
Transport.UpdateKnownMessageSize(iBytes);
end;

target.Read( FProtocol);
finally
Expand All @@ -221,9 +229,15 @@ procedure TDeserializer.Deserialize( const input : TStream; const target : IBase
var before : Int64;
begin
try
before := FStream.Position;
FStream.CopyFrom( input, COPY_ENTIRE_STREAM);
FStream.Position := before;
if Assigned(input) then begin
before := FStream.Position;
ASSERT( before = 0);
FStream.CopyFrom( input, COPY_ENTIRE_STREAM);
FStream.Position := before;
Transport.ResetMessageSizeAndConsumedBytes(); // size has changed
Transport.UpdateKnownMessageSize(FStream.Size);
end;

target.Read( FProtocol);
finally
FStream.Size := 0; // free any allocated memory
Expand Down
109 changes: 85 additions & 24 deletions lib/delphi/test/serializer/TestSerializer.Tests.pas
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ interface

type
TFactoryPair = record
prot : IProtocolFactory;
proto : IProtocolFactory;
trans : ITransportFactory;
end;

Expand All @@ -72,8 +72,9 @@ TTestSerializer = class //extends TestCase {
class procedure Deserialize( const input : TBytes; const target : IBase; const factory : TFactoryPair); overload;
class procedure Deserialize( const input : TStream; const target : IBase; const factory : TFactoryPair); overload;

class procedure ValidateReadToEnd( const input : TBytes; const serial : TDeserializer); overload;
class procedure ValidateReadToEnd( const input : TStream; const serial : TDeserializer); overload;
class procedure Deserialize( const input : TBytes; out target : TGuid; const factory : TFactoryPair); overload;

class procedure ValidateReadToEnd( const serial : TDeserializer); overload;

class function LengthOf( const bytes : TBytes) : Integer; overload; inline;
class function LengthOf( const bytes : IThriftBytes) : Integer; overload; inline;
Expand All @@ -90,6 +91,9 @@ TTestSerializer = class //extends TestCase {
procedure Test_ExceptionStruct( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
procedure Test_SimpleException( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);

procedure Test_ProtocolConformity( const factory : TFactoryPair; const stream : TFileStream);
procedure Test_UuidDeserialization( const factory : TFactoryPair; const stream : TFileStream);

public
constructor Create;
destructor Destroy; override;
Expand Down Expand Up @@ -143,7 +147,7 @@ destructor TTestSerializer.Destroy;
procedure TTestSerializer.AddFactoryCombination( const aProto : IProtocolFactory; const aTrans : ITransportFactory);
var rec : TFactoryPair;
begin
rec.prot := aProto;
rec.proto := aProto;
rec.trans := aTrans;
FProtocols.Add( rec);
end;
Expand Down Expand Up @@ -177,6 +181,53 @@ class function TTestSerializer.DataPtrOf( const bytes : IThriftBytes) : Pointer;
end;


procedure TTestSerializer.Test_ProtocolConformity( const factory : TFactoryPair; const stream : TFileStream);
begin
Test_UuidDeserialization( factory, stream);
// add more tests here
end;


procedure TTestSerializer.Test_UuidDeserialization( const factory : TFactoryPair; const stream : TFileStream);

function CreateGuidBytes : TBytes;
var obj : TObject;
i : Integer;
begin
obj := factory.proto as TObject;

if obj is TJSONProtocolImpl.TFactory then begin
result := TEncoding.UTF8.GetBytes('"00112233-4455-6677-8899-aabbccddeeff"');
Exit;
end;

if (obj is TBinaryProtocolImpl.TFactory)
or (obj is TCompactProtocolImpl.TFactory)
then begin
SetLength(result,16);
for i := 0 to Length(result)-1 do result[i] := (i * $10) + i;
Exit;
end;

raise Exception.Create('Unhandled case');
end;


var tested, correct : TGuid;
bytes : TBytes;
begin
// write
bytes := CreateGuidBytes();

// init + read
Deserialize( bytes, tested, factory);

// check
correct := TGuid.Create('{00112233-4455-6677-8899-aabbccddeeff}');
ASSERT( tested = correct);
end;


procedure TTestSerializer.Test_OneOfEach( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
var tested, correct : IOneOfEach;
bytes : TBytes;
Expand Down Expand Up @@ -385,6 +436,11 @@ procedure TTestSerializer.Test_Serializer_Deserializer;
for factory in FProtocols do begin
Writeln('- '+UserFriendlyName(factory));

// protocol conformity tests
if (method = TMethod.mt_Bytes) and (factory.trans = nil)
then Test_ProtocolConformity( factory, stream);

// normal objects
Test_OneOfEach( method, factory, stream);
Test_CompactStruct( method, factory, stream);
Test_ExceptionStruct( method, factory, stream);
Expand All @@ -402,7 +458,7 @@ procedure TTestSerializer.Test_Serializer_Deserializer;

class function TTestSerializer.UserFriendlyName( const factory : TFactoryPair) : string;
begin
result := Copy( (factory.prot as TObject).ClassName, 2, MAXINT);
result := Copy( (factory.proto as TObject).ClassName, 2, MAXINT);

if factory.trans <> nil
then result := Copy( (factory.trans as TObject).ClassName, 2, MAXINT) +' '+ result;
Expand Down Expand Up @@ -472,7 +528,7 @@ class function TTestSerializer.Serialize(const input : IBase; const factory : TF
config := TThriftConfigurationImpl.Create;
//config.MaxMessageSize := 0; // we don't read anything here

serial := TSerializer.Create( factory.prot, factory.trans, config);
serial := TSerializer.Create( factory.proto, factory.trans, config);
try
result := serial.Serialize( input);
finally
Expand All @@ -488,7 +544,7 @@ class procedure TTestSerializer.Serialize(const input : IBase; const factory : T
config := TThriftConfigurationImpl.Create;
//config.MaxMessageSize := 0; // we don't read anything here

serial := TSerializer.Create( factory.prot, factory.trans, config);
serial := TSerializer.Create( factory.proto, factory.trans, config);
try
serial.Serialize( input, aStream);
finally
Expand All @@ -504,10 +560,10 @@ class procedure TTestSerializer.Deserialize( const input : TBytes; const target
config := TThriftConfigurationImpl.Create;
config.MaxMessageSize := Length(input);

serial := TDeserializer.Create( factory.prot, factory.trans, config);
serial := TDeserializer.Create( factory.proto, factory.trans, config);
try
serial.Deserialize( input, target);
ValidateReadToEnd( input, serial);
ValidateReadToEnd( serial);
finally
serial.Free;
end;
Expand All @@ -521,44 +577,49 @@ class procedure TTestSerializer.Deserialize( const input : TStream; const target
config := TThriftConfigurationImpl.Create;
config.MaxMessageSize := input.Size;

serial := TDeserializer.Create( factory.prot, factory.trans, config);
serial := TDeserializer.Create( factory.proto, factory.trans, config);
try
serial.Deserialize( input, target);
ValidateReadToEnd( input, serial);
ValidateReadToEnd( serial);
finally
serial.Free;
end;
end;


class procedure TTestSerializer.ValidateReadToEnd( const input : TBytes; const serial : TDeserializer);
// we should not have any more byte to read
var dummy : IBase;
class procedure TTestSerializer.Deserialize( const input : TBytes; out target : TGuid; const factory : TFactoryPair);
var serial : TDeserializer;
config : IThriftConfiguration;
begin
config := TThriftConfigurationImpl.Create;
config.MaxMessageSize := Length(input);

serial := TDeserializer.Create( factory.proto, factory.trans, config);
try
dummy := TOneOfEachImpl.Create;
serial.Deserialize( input, dummy);
raise EInOutError.Create('Expected exception not thrown?');
except
on e:TTransportExceptionEndOfFile do {expected};
on e:Exception do raise; // unexpected
serial.Stream.Write(input[0], Length(input));
serial.Stream.Position := 0;
serial.Transport.ResetMessageSizeAndConsumedBytes(); // size has changed

target := serial.Protocol.ReadUuid;
finally
serial.Free;
end;
end;


class procedure TTestSerializer.ValidateReadToEnd( const input : TStream; const serial : TDeserializer);
class procedure TTestSerializer.ValidateReadToEnd( const serial : TDeserializer);
// we should not have any more byte to read
var dummy : IBase;
begin
try
input.Position := 0;
dummy := TOneOfEachImpl.Create;
serial.Deserialize( input, dummy);
serial.Deserialize( nil, dummy);
raise EInOutError.Create('Expected exception not thrown?');
except
on e:TTransportExceptionEndOfFile do {expected};
on e:TTransportException do {expected};
on e:Exception do raise; // unexpected
end;
end;


end.
6 changes: 3 additions & 3 deletions lib/haxe/src/org/apache/thrift/TConfiguration.hx
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ class TConfiguration
public static inline var DEFAULT_MAX_FRAME_SIZE = 16384000; // this value is used consistently across all Thrift libraries
public static inline var DEFAULT_RECURSION_DEPTH = 64;

public var MaxMessageSize(default,null) : Int = DEFAULT_MAX_MESSAGE_SIZE;
public var MaxFrameSize(default,null) : Int = DEFAULT_MAX_FRAME_SIZE;
public var RecursionLimit(default,null) : Int = DEFAULT_RECURSION_DEPTH;
public var MaxMessageSize(default,default) : Int = DEFAULT_MAX_MESSAGE_SIZE;
public var MaxFrameSize(default,default) : Int = DEFAULT_MAX_FRAME_SIZE;
public var RecursionLimit(default,default) : Int = DEFAULT_RECURSION_DEPTH;

// TODO(JensG): add connection and i/o timeouts

Expand Down
88 changes: 88 additions & 0 deletions lib/haxe/src/org/apache/thrift/transport/TMemoryStream.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.apache.thrift.transport;

import haxe.io.Bytes;
import haxe.io.BytesBuffer;
import haxe.io.Output;

class TMemoryStream implements TStream {

private var Data : Bytes;
public var Position(default,default) : Int;

public function new( data : Bytes = null) {
var target = new BytesBuffer();
if ( data != null) {
for ( i in 0...data.length) {
target.addByte( data.get(i));
++Position;
}
}
Data = target.getBytes();
}

private function IsEof() : Bool {
return (0 > Position) || (Position >= Data.length);
}

public function Close() : Void {
var target = new BytesBuffer();
Data = target.getBytes();
Position = 0;
}

public function Peek() : Bool {
return (! IsEof());
}

// read count bytes into buf starting at offset
public function Read( buf : Bytes, offset : Int, count : Int) : Int {
var numRead = 0;

for ( i in 0...count) {
if ( IsEof())
break;

buf.set( offset + i, Data.get( Position++));
++numRead;
}

return numRead;
}

// write count bytes from buf starting at offset
public function Write( buf : Bytes, offset : Int, count : Int) : Void {
var numBytes = buf.length - offset;
if ( numBytes > count) {
numBytes = count;
}

for ( i in 0...numBytes) {
Data.set( Position + i, buf.get( offset + i));
}
}

public function Flush() : Void {
// nothing to do
}

}

2 changes: 1 addition & 1 deletion lib/haxe/test/HaxeTests.hxproj
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ thrift -r -gen haxe ../../../lib/rb/benchmark/Benchmark.thrift</preBuildCommand
<options>
<option showHiddenPaths="False" />
<option testMovie="Custom" />
<option testMovieCommand="bin/HaxeTests/Main.exe server multiplex" />
<option testMovieCommand="bin/HaxeTests/Main.exe server constants" />
</options>
<!-- Plugin storage -->
<storage />
Expand Down
Loading
Loading