(*
 * 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;

interface

uses
  Classes, Windows, SysUtils,
  Thrift.Protocol,
  Thrift.Transport,
  Thrift.Stream;


type
  // Generic utility for easily serializing objects into a byte array or Stream.
  TSerializer = class
  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;

    // 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
  private
    FStream    : TMemoryStream;
    FTransport : ITransport;
    FProtocol  : IProtocol;

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

    // Create a new TDeserializer.
    // It will use the TProtocol specified by the factory that is passed in.
    constructor Create( const factory : IProtocolFactory);  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
  Create( TBinaryProtocolImpl.TFactory.Create);
end;


constructor TSerializer.Create( const factory : IProtocolFactory);
// 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);
  FProtocol  := factory.GetProtocol( FTransport);
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);
    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);
    aStm.CopyFrom( FStream, COPY_ENTIRE_STREAM);
  finally
    FStream.Size := 0;  // free any allocated memory
  end;
end;


{ TDeserializer }


constructor TDeserializer.Create();
// Create a new TDeserializer that uses the TBinaryProtocol by default.
begin
  Create( TBinaryProtocolImpl.TFactory.Create);
end;


constructor TDeserializer.Create( const factory : IProtocolFactory);
// 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);
  FProtocol  := factory.GetProtocol( FTransport);
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.

