(*
 * 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.
 *)
unit Thrift.Serializer;

{$I Thrift.Defines.inc}

interface

uses
  {$IFDEF OLD_UNIT_NAMES}
  Classes, Windows, SysUtils,
  {$ELSE}
  System.Classes, Winapi.Windows, System.SysUtils,
  {$ENDIF}
  Thrift.Protocol,
  Thrift.Transport,
  Thrift.Stream;


type
  // Generic utility for easily serializing objects into a byte array or Stream.
  TSerializer = class
  strict private
    FStream    : TMemoryStream;
    FTransport : ITransport;
    FProtocol  : IProtocol;

  public
    // Create a new TSerializer that uses the TBinaryProtocol by default.
    constructor Create;  overload;

    // Create a new TSerializer.
    // It will use the TProtocol specified by the factory that is passed in.
    constructor Create( const factory : IProtocolFactory);  overload;

    // Create a new TSerializer.
    // It will use the TProtocol and layered transports specified by the factories that are passed in.
    constructor Create( const protfact : IProtocolFactory; const transfact : ITransportFactory);  overload;

    // DTOR
    destructor Destroy;  override;

    // Serialize the Thrift object.
    function  Serialize( const input : IBase) : TBytes;  overload;
    procedure Serialize( const input : IBase; const aStm : TStream);  overload;
  end;


  // Generic utility for easily deserializing objects from byte array or Stream.
  TDeserializer = class
  strict private
    FStream    : TMemoryStream;
    FTransport : ITransport;
    FProtocol  : IProtocol;

  public
    // Create a new TDeserializer that uses the TBinaryProtocol by default.
    constructor Create( const aMaxMessageSize : Integer = DEFAULT_MAX_MESSAGE_SIZE);  overload;

    // Create a new TDeserializer.
    // It will use the TProtocol specified by the factory that is passed in.
    constructor Create( const factory : IProtocolFactory;
                        const aMaxMessageSize : Integer = DEFAULT_MAX_MESSAGE_SIZE);  overload;

    // Create a new TDeserializer.
    // It will use the TProtocol and layered transports specified by the factories that are passed in.
    constructor Create( const protfact : IProtocolFactory;
                        const transfact : ITransportFactory;
                        const aMaxMessageSize : Integer = DEFAULT_MAX_MESSAGE_SIZE);  overload;

    // 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;
  end;



implementation


{ TSerializer }


constructor TSerializer.Create;
// Create a new TSerializer that uses the TBinaryProtocol by default.
begin
  //no inherited;
  Create( TBinaryProtocolImpl.TFactory.Create, nil);
end;


constructor TSerializer.Create( const factory : IProtocolFactory);
// Create a new TSerializer.
// It will use the TProtocol specified by the factory that is passed in.
begin
  //no inherited;
  Create( factory, nil);
end;


constructor TSerializer.Create( const protfact : IProtocolFactory; const transfact : ITransportFactory);
// Create a new TSerializer.
// It will use the TProtocol specified by the factory that is passed in.
var adapter : IThriftStream;
begin
  inherited Create;
  FStream    := TMemoryStream.Create;
  adapter    := TThriftStreamAdapterDelphi.Create( FStream, FALSE);
  FTransport := TStreamTransportImpl.Create( nil, adapter, TTransportControlImpl.Create(0));  // we don't read anything here
  if transfact <> nil then FTransport := transfact.GetTransport( FTransport);
  FProtocol  := protfact.GetProtocol( FTransport);

  if not FTransport.IsOpen
  then FTransport.Open;
end;


destructor TSerializer.Destroy;
begin
  try
    FProtocol  := nil;
    FTransport := nil;
    FreeAndNil( FStream);
  finally
    inherited Destroy;
  end;
end;


function TSerializer.Serialize( const input : IBase) : TBytes;
// Serialize the Thrift object into a byte array. The process is simple,
// just clear the byte array output, write the object into it, and grab the
// raw bytes.
var iBytes : Int64;
begin
  try
    FStream.Size := 0;
    input.Write( FProtocol);
    FTransport.Flush;

    SetLength( result, FStream.Size);
    iBytes := Length(result);
    if iBytes > 0
    then Move( FStream.Memory^, result[0], iBytes);
  finally
    FStream.Size := 0;  // free any allocated memory
  end;
end;


procedure TSerializer.Serialize( const input : IBase; const aStm : TStream);
// Serialize the Thrift object into a byte array. The process is simple,
// just clear the byte array output, write the object into it, and grab the
// raw bytes.
const COPY_ENTIRE_STREAM = 0;
begin
  try
    FStream.Size := 0;
    input.Write( FProtocol);
    FTransport.Flush;

    aStm.CopyFrom( FStream, COPY_ENTIRE_STREAM);
  finally
    FStream.Size := 0;  // free any allocated memory
  end;
end;


{ TDeserializer }


constructor TDeserializer.Create( const aMaxMessageSize : Integer);
// Create a new TDeserializer that uses the TBinaryProtocol by default.
begin
  //no inherited;
  Create( TBinaryProtocolImpl.TFactory.Create, nil, aMaxMessageSize);
end;


constructor TDeserializer.Create( const factory : IProtocolFactory; const aMaxMessageSize : Integer);
// Create a new TDeserializer.
// It will use the TProtocol specified by the factory that is passed in.
begin
  //no inherited;
  Create( factory, nil, aMaxMessageSize);
end;


constructor TDeserializer.Create( const protfact : IProtocolFactory;
                                  const transfact : ITransportFactory;
                                  const aMaxMessageSize : Integer = DEFAULT_MAX_MESSAGE_SIZE);
// Create a new TDeserializer.
// It will use the TProtocol specified by the factory that is passed in.
var adapter : IThriftStream;
begin
  inherited Create;
  FStream    := TMemoryStream.Create;
  adapter    := TThriftStreamAdapterDelphi.Create( FStream, FALSE);
  FTransport := TStreamTransportImpl.Create( adapter, nil, TTransportControlImpl.Create(aMaxMessageSize));
  if transfact <> nil then FTransport := transfact.GetTransport( FTransport);
  FProtocol  := protfact.GetProtocol( FTransport);

  if not FTransport.IsOpen
  then FTransport.Open;
end;


destructor TDeserializer.Destroy;
begin
  try
    FProtocol  := nil;
    FTransport := nil;
    FreeAndNil( FStream);
  finally
    inherited Destroy;
  end;
end;


procedure TDeserializer.Deserialize( const input : TBytes; const target : IBase);
// Deserialize the Thrift object data from the byte array.
var iBytes : Int64;
begin
  try
    iBytes := Length(input);
    FStream.Size := iBytes;
    if iBytes > 0
    then Move( input[0], FStream.Memory^, iBytes);

    target.Read( FProtocol);
  finally
    FStream.Size := 0;  // free any allocated memory
  end;
end;


procedure TDeserializer.Deserialize( const input : TStream; const target : IBase);
// Deserialize the Thrift object data from the byte array.
const COPY_ENTIRE_STREAM = 0;
var before : Int64;
begin
  try
    before := FStream.Position;
    FStream.CopyFrom( input, COPY_ENTIRE_STREAM);
    FStream.Position := before;
    target.Read( FProtocol);
  finally
    FStream.Size := 0;  // free any allocated memory
  end;
end;


end.

