unit XData.Bind.Converter;

{$I XData.inc}

interface

uses
  Rtti, TypInfo, SysUtils,
  Aurelius.Types.Blob,
  XData.Model.Classes;

function BindValueToUrl(const Value: TValue; const Info: PTypeInfo;
  UrlConverter: TXDataTypeConverter): string;
function BindUrlToValue(const Literal: string; const Info: PTypeInfo;
  UrlConverter: TXDataTypeConverter): TValue;

implementation

function BindValueToUrl(const Value: TValue; const Info: PTypeInfo;
  UrlConverter: TXDataTypeConverter): string;
var
  TempValue: TValue;
begin
  if Info = TypeInfo(TBlob) then
  begin
    TempValue := TValue.From<TBytes>(Value.AsType<TBlob>.AsBytes);
  end
  else
    TempValue := Value;

  Result := UrlConverter.ValueToUrl(TempValue, nil);
end;

function BindUrlToValue(const Literal: string; const Info: PTypeInfo;
  UrlConverter: TXDataTypeConverter): TValue;
var
  TempValue: TValue;
  Blob: TBlob;
begin
  TempValue := UrlConverter.UrlToValue(Literal, nil);

  // Make sure value is same type of parameter type
  // This should be replaced by a factory/registration system
  if Info = TypeInfo(TBlob) then
  begin
    Blob.AsBytes := TempValue.AsType<TBytes>;
    Result := TValue.From<TBlob>(Blob);
  end
  else
  if Info.Kind = tkEnumeration then
    Result := TValue.FromOrdinal(Info, TempValue.AsOrdinal)
  else
  if not TempValue.TryCast(Info, Result) then
    raise EConvertFromUrlError.Create(nil, Literal);
end;

end.
