Data Types
This commit is contained in:
@@ -28,6 +28,7 @@ type
|
|||||||
FArrayType: IDataArrayType;
|
FArrayType: IDataArrayType;
|
||||||
FItems: TArray<IDataValue>;
|
FItems: TArray<IDataValue>;
|
||||||
function GetDataType: IDataType;
|
function GetDataType: IDataType;
|
||||||
|
function GetAsString: string;
|
||||||
function GetElementCount: Integer;
|
function GetElementCount: Integer;
|
||||||
function GetItem(Idx: Integer): IDataValue;
|
function GetItem(Idx: Integer): IDataValue;
|
||||||
public
|
public
|
||||||
@@ -57,6 +58,27 @@ begin
|
|||||||
Result := FArrayType;
|
Result := FArrayType;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TImplDataArrayValue.GetAsString: string;
|
||||||
|
var
|
||||||
|
sb: TStringBuilder;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
sb := TStringBuilder.Create;
|
||||||
|
try
|
||||||
|
sb.Append('[');
|
||||||
|
for i := 0 to High(FItems) do
|
||||||
|
begin
|
||||||
|
sb.Append(FItems[i].AsString);
|
||||||
|
if (i < High(FItems)) then
|
||||||
|
sb.Append(', ');
|
||||||
|
end;
|
||||||
|
sb.Append(']');
|
||||||
|
Result := sb.ToString;
|
||||||
|
finally
|
||||||
|
sb.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function TImplDataArrayValue.GetElementCount: Integer;
|
function TImplDataArrayValue.GetElementCount: Integer;
|
||||||
begin
|
begin
|
||||||
Result := Length(FItems);
|
Result := Length(FItems);
|
||||||
|
|||||||
@@ -0,0 +1,132 @@
|
|||||||
|
unit Myc.Data.Types.Enum;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
System.SysUtils,
|
||||||
|
System.Generics.Collections,
|
||||||
|
Myc.Data.Types;
|
||||||
|
|
||||||
|
type
|
||||||
|
TImplDataEnumValue = class(TInterfacedObject, IDataEnumValue)
|
||||||
|
private
|
||||||
|
FDataType: IDataEnumType;
|
||||||
|
FValue: Integer;
|
||||||
|
function GetDataType: IDataType;
|
||||||
|
function GetAsString: string;
|
||||||
|
function GetValue: Integer;
|
||||||
|
public
|
||||||
|
constructor Create(const ADataType: IDataEnumType; const AValue: Integer);
|
||||||
|
end;
|
||||||
|
|
||||||
|
TImplDataEnumType = class(TInterfacedObject, IDataEnumType)
|
||||||
|
private
|
||||||
|
FName: string;
|
||||||
|
FIdentifiers: TArray<string>;
|
||||||
|
FIdentifierMap: TDictionary<string, Integer>;
|
||||||
|
function GetName: String;
|
||||||
|
function GetKind: TDataKind;
|
||||||
|
function GetIdentifier(Idx: Integer): string;
|
||||||
|
function GetIdentifierCount: Integer;
|
||||||
|
function IndexOf(const AIdentifier: string): Integer;
|
||||||
|
function CreateValue(const AValue: Integer): IDataEnumValue; overload;
|
||||||
|
function CreateValue(const AIdentifier: string): IDataEnumValue; overload;
|
||||||
|
public
|
||||||
|
constructor Create(const AName: string; const AIdentifiers: array of string);
|
||||||
|
destructor Destroy; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
{ TImplDataEnumType }
|
||||||
|
|
||||||
|
constructor TImplDataEnumType.Create(const AName: string; const AIdentifiers: array of string);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
FName := AName;
|
||||||
|
FIdentifierMap := TDictionary<string, Integer>.Create;
|
||||||
|
SetLength(FIdentifiers, Length(AIdentifiers));
|
||||||
|
for i := 0 to High(AIdentifiers) do
|
||||||
|
begin
|
||||||
|
if FIdentifierMap.ContainsKey(AIdentifiers[i]) then
|
||||||
|
raise EArgumentException.CreateFmt('Duplicate identifier: %s', [AIdentifiers[i]]);
|
||||||
|
FIdentifiers[i] := AIdentifiers[i];
|
||||||
|
FIdentifierMap.Add(AIdentifiers[i], i);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TImplDataEnumType.Destroy;
|
||||||
|
begin
|
||||||
|
FIdentifierMap.Free;
|
||||||
|
inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TImplDataEnumType.GetName: String;
|
||||||
|
begin
|
||||||
|
Result := FName;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TImplDataEnumType.GetKind: TDataKind;
|
||||||
|
begin
|
||||||
|
Result := dkEnum;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TImplDataEnumType.GetIdentifier(Idx: Integer): string;
|
||||||
|
begin
|
||||||
|
Result := FIdentifiers[Idx];
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TImplDataEnumType.GetIdentifierCount: Integer;
|
||||||
|
begin
|
||||||
|
Result := Length(FIdentifiers);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TImplDataEnumType.IndexOf(const AIdentifier: string): Integer;
|
||||||
|
begin
|
||||||
|
if not FIdentifierMap.TryGetValue(AIdentifier, Result) then
|
||||||
|
Result := -1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TImplDataEnumType.CreateValue(const AValue: Integer): IDataEnumValue;
|
||||||
|
begin
|
||||||
|
if (AValue < 0) or (AValue >= Length(FIdentifiers)) then
|
||||||
|
raise EArgumentException.Create('Invalid enum value');
|
||||||
|
Result := TImplDataEnumValue.Create(Self, AValue);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TImplDataEnumType.CreateValue(const AIdentifier: string): IDataEnumValue;
|
||||||
|
var
|
||||||
|
idx: Integer;
|
||||||
|
begin
|
||||||
|
idx := IndexOf(AIdentifier);
|
||||||
|
if idx < 0 then
|
||||||
|
raise EArgumentException.CreateFmt('Unknown identifier: %s', [AIdentifier]);
|
||||||
|
Result := CreateValue(idx);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TImplDataEnumValue }
|
||||||
|
|
||||||
|
constructor TImplDataEnumValue.Create(const ADataType: IDataEnumType; const AValue: Integer);
|
||||||
|
begin
|
||||||
|
FDataType := ADataType;
|
||||||
|
FValue := AValue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TImplDataEnumValue.GetDataType: IDataType;
|
||||||
|
begin
|
||||||
|
Result := FDataType;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TImplDataEnumValue.GetAsString: string;
|
||||||
|
begin
|
||||||
|
Result := FDataType.Identifiers[FValue];
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TImplDataEnumValue.GetValue: Integer;
|
||||||
|
begin
|
||||||
|
Result := FValue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
||||||
@@ -16,6 +16,7 @@ type
|
|||||||
|
|
||||||
// IDataValue
|
// IDataValue
|
||||||
function GetDataType: IDataType;
|
function GetDataType: IDataType;
|
||||||
|
function GetAsString: string;
|
||||||
|
|
||||||
// IDataFloatValue
|
// IDataFloatValue
|
||||||
function GetValue: Double;
|
function GetValue: Double;
|
||||||
@@ -49,6 +50,11 @@ begin
|
|||||||
Result := TImplDataFloatType.Singleton;
|
Result := TImplDataFloatType.Singleton;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TImplDataFloatValue.GetAsString: string;
|
||||||
|
begin
|
||||||
|
Result := FloatToStr(FValue);
|
||||||
|
end;
|
||||||
|
|
||||||
function TImplDataFloatValue.GetValue: Double;
|
function TImplDataFloatValue.GetValue: Double;
|
||||||
begin
|
begin
|
||||||
Result := FValue;
|
Result := FValue;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ type
|
|||||||
|
|
||||||
// IDataValue
|
// IDataValue
|
||||||
function GetDataType: IDataType;
|
function GetDataType: IDataType;
|
||||||
|
function GetAsString: string;
|
||||||
|
|
||||||
// IDataOrdinalValue
|
// IDataOrdinalValue
|
||||||
function GetValue: Int64;
|
function GetValue: Int64;
|
||||||
@@ -49,6 +50,11 @@ begin
|
|||||||
Result := TImplDataOrdinalType.Singleton;
|
Result := TImplDataOrdinalType.Singleton;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TImplDataOrdinalValue.GetAsString: string;
|
||||||
|
begin
|
||||||
|
Result := FValue.ToString;
|
||||||
|
end;
|
||||||
|
|
||||||
function TImplDataOrdinalValue.GetValue: Int64;
|
function TImplDataOrdinalValue.GetValue: Int64;
|
||||||
begin
|
begin
|
||||||
Result := FValue;
|
Result := FValue;
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ type
|
|||||||
FDataType: IDataRecordType;
|
FDataType: IDataRecordType;
|
||||||
FItems: TArray<IDataValue>;
|
FItems: TArray<IDataValue>;
|
||||||
function GetDataType: IDataType;
|
function GetDataType: IDataType;
|
||||||
|
function GetAsString: string;
|
||||||
function GetItem(Idx: Integer): IDataValue;
|
function GetItem(Idx: Integer): IDataValue;
|
||||||
public
|
public
|
||||||
constructor Create(const ADataType: IDataRecordType; const AItems: array of IDataValue);
|
constructor Create(const ADataType: IDataRecordType; const AItems: array of IDataValue);
|
||||||
@@ -97,6 +98,31 @@ begin
|
|||||||
Result := FDataType;
|
Result := FDataType;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TImplDataRecordValue.GetAsString: string;
|
||||||
|
var
|
||||||
|
sb: TStringBuilder;
|
||||||
|
i: Integer;
|
||||||
|
recordType: IDataRecordType;
|
||||||
|
begin
|
||||||
|
recordType := FDataType;
|
||||||
|
sb := TStringBuilder.Create;
|
||||||
|
try
|
||||||
|
sb.Append('<');
|
||||||
|
for i := 0 to High(FItems) do
|
||||||
|
begin
|
||||||
|
sb.Append(recordType.Fields[i].Name);
|
||||||
|
sb.Append(': ');
|
||||||
|
sb.Append(FItems[i].AsString);
|
||||||
|
if (i < High(FItems)) then
|
||||||
|
sb.Append(', ');
|
||||||
|
end;
|
||||||
|
sb.Append('>');
|
||||||
|
Result := sb.ToString;
|
||||||
|
finally
|
||||||
|
sb.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function TImplDataRecordValue.GetItem(Idx: Integer): IDataValue;
|
function TImplDataRecordValue.GetItem(Idx: Integer): IDataValue;
|
||||||
begin
|
begin
|
||||||
Result := FItems[Idx];
|
Result := FItems[Idx];
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ type
|
|||||||
private
|
private
|
||||||
FValue: string;
|
FValue: string;
|
||||||
function GetDataType: IDataType;
|
function GetDataType: IDataType;
|
||||||
|
function GetAsString: string;
|
||||||
function GetValue: string;
|
function GetValue: string;
|
||||||
public
|
public
|
||||||
constructor Create(const AValue: string);
|
constructor Create(const AValue: string);
|
||||||
@@ -65,6 +66,11 @@ begin
|
|||||||
Result := TImplDataTextType.Singleton;
|
Result := TImplDataTextType.Singleton;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TImplDataTextValue.GetAsString: string;
|
||||||
|
begin
|
||||||
|
Result := FValue;
|
||||||
|
end;
|
||||||
|
|
||||||
function TImplDataTextValue.GetValue: string;
|
function TImplDataTextValue.GetValue: string;
|
||||||
begin
|
begin
|
||||||
Result := FValue;
|
Result := FValue;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ type
|
|||||||
private
|
private
|
||||||
FValue: TDateTime;
|
FValue: TDateTime;
|
||||||
function GetDataType: IDataType;
|
function GetDataType: IDataType;
|
||||||
|
function GetAsString: string;
|
||||||
function GetValue: TDateTime;
|
function GetValue: TDateTime;
|
||||||
public
|
public
|
||||||
constructor Create(const AValue: TDateTime);
|
constructor Create(const AValue: TDateTime);
|
||||||
@@ -65,6 +66,11 @@ begin
|
|||||||
Result := TImplDataTimestampType.Singleton;
|
Result := TImplDataTimestampType.Singleton;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TImplDataTimestampValue.GetAsString: string;
|
||||||
|
begin
|
||||||
|
Result := DateTimeToStr(FValue);
|
||||||
|
end;
|
||||||
|
|
||||||
function TImplDataTimestampValue.GetValue: TDateTime;
|
function TImplDataTimestampValue.GetValue: TDateTime;
|
||||||
begin
|
begin
|
||||||
Result := FValue;
|
Result := FValue;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ type
|
|||||||
private
|
private
|
||||||
FItems: TArray<IDataValue>;
|
FItems: TArray<IDataValue>;
|
||||||
function GetDataType: IDataType;
|
function GetDataType: IDataType;
|
||||||
|
function GetAsString: string;
|
||||||
function GetItemCount: Integer;
|
function GetItemCount: Integer;
|
||||||
function GetItem(Idx: Integer): IDataValue;
|
function GetItem(Idx: Integer): IDataValue;
|
||||||
public
|
public
|
||||||
@@ -51,6 +52,27 @@ begin
|
|||||||
Result := TImplDataTupleType.Singleton;
|
Result := TImplDataTupleType.Singleton;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TImplDataTupleValue.GetAsString: string;
|
||||||
|
var
|
||||||
|
sb: TStringBuilder;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
sb := TStringBuilder.Create;
|
||||||
|
try
|
||||||
|
sb.Append('(');
|
||||||
|
for i := 0 to High(FItems) do
|
||||||
|
begin
|
||||||
|
sb.Append(FItems[i].AsString);
|
||||||
|
if (i < High(FItems)) then
|
||||||
|
sb.Append(', ');
|
||||||
|
end;
|
||||||
|
sb.Append(')');
|
||||||
|
Result := sb.ToString;
|
||||||
|
finally
|
||||||
|
sb.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function TImplDataTupleValue.GetItem(Idx: Integer): IDataValue;
|
function TImplDataTupleValue.GetItem(Idx: Integer): IDataValue;
|
||||||
begin
|
begin
|
||||||
Result := FItems[Idx];
|
Result := FItems[Idx];
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ uses
|
|||||||
System.SysUtils;
|
System.SysUtils;
|
||||||
|
|
||||||
type
|
type
|
||||||
TDataKind = (dkOrdinal, dkFloat, dkText, dkTimestamp, dkRecord, dkTuple, dkArray);
|
TDataKind = (dkOrdinal, dkFloat, dkText, dkTimestamp, dkRecord, dkTuple, dkArray, dkEnum);
|
||||||
|
|
||||||
IDataType = interface
|
IDataType = interface
|
||||||
function GetName: String;
|
function GetName: String;
|
||||||
@@ -18,7 +18,9 @@ type
|
|||||||
|
|
||||||
IDataValue = interface
|
IDataValue = interface
|
||||||
function GetDataType: IDataType;
|
function GetDataType: IDataType;
|
||||||
|
function GetAsString: string;
|
||||||
property DataType: IDataType read GetDataType;
|
property DataType: IDataType read GetDataType;
|
||||||
|
property AsString: string read GetAsString;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
IDataOrdinalValue = interface(IDataValue)
|
IDataOrdinalValue = interface(IDataValue)
|
||||||
@@ -57,6 +59,21 @@ type
|
|||||||
function CreateValue(const AValue: TDateTime): IDataTimestampValue;
|
function CreateValue(const AValue: TDateTime): IDataTimestampValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
IDataEnumValue = interface(IDataValue)
|
||||||
|
function GetValue: Integer;
|
||||||
|
property Value: Integer read GetValue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
IDataEnumType = interface(IDataType)
|
||||||
|
function GetIdentifier(Idx: Integer): string;
|
||||||
|
function GetIdentifierCount: Integer;
|
||||||
|
function IndexOf(const AIdentifier: string): Integer;
|
||||||
|
function CreateValue(const AValue: Integer): IDataEnumValue; overload;
|
||||||
|
function CreateValue(const AIdentifier: string): IDataEnumValue; overload;
|
||||||
|
property IdentifierCount: Integer read GetIdentifierCount;
|
||||||
|
property Identifiers[Idx: Integer]: string read GetIdentifier; default;
|
||||||
|
end;
|
||||||
|
|
||||||
IDataRecordValue = interface(IDataValue)
|
IDataRecordValue = interface(IDataValue)
|
||||||
function GetItem(Idx: Integer): IDataValue;
|
function GetItem(Idx: Integer): IDataValue;
|
||||||
property Items[Idx: Integer]: IDataValue read GetItem; default;
|
property Items[Idx: Integer]: IDataValue read GetItem; default;
|
||||||
@@ -127,6 +144,7 @@ type
|
|||||||
class function ArrayOfType(const AElementType: IDataType): IDataArrayType; static;
|
class function ArrayOfType(const AElementType: IDataType): IDataArrayType; static;
|
||||||
class function RecordOf(const Fields: TArray<TRecordField>): IDataRecordType; overload; static;
|
class function RecordOf(const Fields: TArray<TRecordField>): IDataRecordType; overload; static;
|
||||||
class function RecordOf(const Fields: array of TRecordField): IDataRecordType; overload; static;
|
class function RecordOf(const Fields: array of TRecordField): IDataRecordType; overload; static;
|
||||||
|
class function EnumOf(const AName: string; const AIdentifiers: array of string): IDataEnumType; static;
|
||||||
|
|
||||||
property DataType: IDataType read FDataType;
|
property DataType: IDataType read FDataType;
|
||||||
property Name: String read GetName;
|
property Name: String read GetName;
|
||||||
@@ -147,6 +165,7 @@ type
|
|||||||
function AsRecord: IDataRecordValue;
|
function AsRecord: IDataRecordValue;
|
||||||
function AsTuple: IDataTupleValue;
|
function AsTuple: IDataTupleValue;
|
||||||
function AsArray: IDataArrayValue;
|
function AsArray: IDataArrayValue;
|
||||||
|
function AsEnum: IDataEnumValue;
|
||||||
|
|
||||||
class operator Implicit(const A: IDataValue): TDataValue; overload;
|
class operator Implicit(const A: IDataValue): TDataValue; overload;
|
||||||
class operator Implicit(const A: TDataValue): IDataValue; overload;
|
class operator Implicit(const A: TDataValue): IDataValue; overload;
|
||||||
@@ -173,7 +192,8 @@ uses
|
|||||||
Myc.Data.Types.Timestamp,
|
Myc.Data.Types.Timestamp,
|
||||||
Myc.Data.Types.Arrays,
|
Myc.Data.Types.Arrays,
|
||||||
Myc.Data.Types.Records,
|
Myc.Data.Types.Records,
|
||||||
Myc.Data.Types.Tuple;
|
Myc.Data.Types.Tuple,
|
||||||
|
Myc.Data.Types.Enum;
|
||||||
|
|
||||||
{ TRecordField }
|
{ TRecordField }
|
||||||
|
|
||||||
@@ -262,6 +282,11 @@ begin
|
|||||||
Result := RecordOf(tFields);
|
Result := RecordOf(tFields);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
class function TDataType.EnumOf(const AName: string; const AIdentifiers: array of string): IDataEnumType;
|
||||||
|
begin
|
||||||
|
Result := TImplDataEnumType.Create(AName, AIdentifiers);
|
||||||
|
end;
|
||||||
|
|
||||||
class function TDataType.Text: IDataTextType;
|
class function TDataType.Text: IDataTextType;
|
||||||
begin
|
begin
|
||||||
Result := TImplDataTextType.Singleton;
|
Result := TImplDataTextType.Singleton;
|
||||||
@@ -343,6 +368,13 @@ begin
|
|||||||
Result := IDataTupleValue(FDataValue);
|
Result := IDataTupleValue(FDataValue);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TDataValue.AsEnum: IDataEnumValue;
|
||||||
|
begin
|
||||||
|
if FDataValue.DataType.Kind <> dkEnum then
|
||||||
|
raise EInvalidCast.Create('Enum expected');
|
||||||
|
Result := IDataEnumValue(FDataValue);
|
||||||
|
end;
|
||||||
|
|
||||||
class function TDataValue.FromOrdinal(const AValue: Int64): IDataOrdinalValue;
|
class function TDataValue.FromOrdinal(const AValue: Int64): IDataOrdinalValue;
|
||||||
begin
|
begin
|
||||||
Result := TImplDataOrdinalType.Singleton.CreateValue(AValue);
|
Result := TImplDataOrdinalType.Singleton.CreateValue(AValue);
|
||||||
|
|||||||
+114
-1
@@ -23,6 +23,12 @@ type
|
|||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
procedure TestTimestamps;
|
procedure TestTimestamps;
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
procedure TestEnums;
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
procedure TestAsString;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@@ -253,7 +259,7 @@ begin
|
|||||||
Assert.AreEqual(dkTimestamp, tsType.Kind, 'Type kind should be dkTimestamp');
|
Assert.AreEqual(dkTimestamp, tsType.Kind, 'Type kind should be dkTimestamp');
|
||||||
|
|
||||||
// --- 2. Test Value Creation and Access ---
|
// --- 2. Test Value Creation and Access ---
|
||||||
now := Now;
|
now := System.Sysutils.Now;
|
||||||
tsValue1 := TDataValue.FromTimestamp(now);
|
tsValue1 := TDataValue.FromTimestamp(now);
|
||||||
|
|
||||||
Assert.IsNotNull(tsValue1, 'TimestampValue should be created');
|
Assert.IsNotNull(tsValue1, 'TimestampValue should be created');
|
||||||
@@ -277,6 +283,113 @@ begin
|
|||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TMyTestObject.TestEnums;
|
||||||
|
var
|
||||||
|
colorType: IDataEnumType;
|
||||||
|
red, green, blue: IDataEnumValue;
|
||||||
|
begin
|
||||||
|
// --- 1. Test Type Creation ---
|
||||||
|
colorType := TDataType.EnumOf('Color', ['Red', 'Green', 'Blue']);
|
||||||
|
|
||||||
|
Assert.IsNotNull(colorType, 'EnumType should be created');
|
||||||
|
Assert.AreEqual('Color', colorType.Name, 'Name should be Color');
|
||||||
|
Assert.AreEqual(dkEnum, colorType.Kind, 'Kind should be dkEnum');
|
||||||
|
Assert.AreEqual(3, colorType.IdentifierCount, 'IdentifierCount should be 3');
|
||||||
|
Assert.AreEqual('Red', colorType.Identifiers[0], 'Identifier at index 0 should be Red');
|
||||||
|
Assert.AreEqual('Green', colorType.Identifiers[1], 'Identifier at index 1 should be Green');
|
||||||
|
Assert.AreEqual('Blue', colorType.Identifiers[2], 'Identifier at index 2 should be Blue');
|
||||||
|
Assert.AreEqual(1, colorType.IndexOf('Green'), 'IndexOf Green should be 1');
|
||||||
|
Assert.AreEqual(-1, colorType.IndexOf('Yellow'), 'IndexOf Yellow should be -1');
|
||||||
|
|
||||||
|
// --- 2. Test Value Creation and Access ---
|
||||||
|
red := colorType.CreateValue(0);
|
||||||
|
green := colorType.CreateValue('Green');
|
||||||
|
blue := TDataValue(colorType.CreateValue(2)).AsEnum;
|
||||||
|
|
||||||
|
Assert.IsNotNull(red, 'EnumValue from index should be created');
|
||||||
|
Assert.AreSame(colorType, red.DataType, 'Red should have the correct data type');
|
||||||
|
Assert.AreEqual(0, red.Value, 'Value of Red should be 0');
|
||||||
|
Assert.AreEqual('Red', red.AsString, 'AsText of Red should be Red');
|
||||||
|
|
||||||
|
Assert.IsNotNull(green, 'EnumValue from identifier should be created');
|
||||||
|
Assert.AreSame(colorType, green.DataType, 'Green should have the correct data type');
|
||||||
|
Assert.AreEqual(1, green.Value, 'Value of Green should be 1');
|
||||||
|
Assert.AreEqual('Green', green.AsString, 'AsText of Green should be Green');
|
||||||
|
|
||||||
|
Assert.AreEqual(2, blue.Value, 'Value of Blue should be 2');
|
||||||
|
|
||||||
|
// --- 3. Test Validation and Error Handling ---
|
||||||
|
// Test creating a type with duplicate identifiers
|
||||||
|
Assert.WillRaise(
|
||||||
|
procedure begin TDataType.EnumOf('Fails', ['A', 'B', 'A']); end,
|
||||||
|
EArgumentException,
|
||||||
|
'Duplicate identifiers should raise an exception'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test creating a value with an invalid index
|
||||||
|
Assert.WillRaise(procedure begin colorType.CreateValue(3); end, EArgumentException, 'Invalid index should raise an exception');
|
||||||
|
Assert.WillRaise(procedure begin colorType.CreateValue(-1); end, EArgumentException, 'Negative index should raise an exception');
|
||||||
|
|
||||||
|
// Test creating a value with an unknown identifier
|
||||||
|
Assert.WillRaise(
|
||||||
|
procedure begin colorType.CreateValue('Yellow'); end,
|
||||||
|
EArgumentException,
|
||||||
|
'Unknown identifier should raise an exception'
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMyTestObject.TestAsString;
|
||||||
|
var
|
||||||
|
ordinalValue: IDataOrdinalValue;
|
||||||
|
floatValue: IDataFloatValue;
|
||||||
|
textValue: IDataTextValue;
|
||||||
|
tsValue: IDataTimestampValue;
|
||||||
|
enumValue: IDataEnumValue;
|
||||||
|
arrayValue: IDataArrayValue;
|
||||||
|
recordValue: IDataRecordValue;
|
||||||
|
tupleValue: IDataTupleValue;
|
||||||
|
colorType: IDataEnumType;
|
||||||
|
personType: IDataRecordType;
|
||||||
|
intArrayType: IDataArrayType;
|
||||||
|
now: TDateTime;
|
||||||
|
begin
|
||||||
|
// Ordinal
|
||||||
|
ordinalValue := TDataValue.FromOrdinal(123);
|
||||||
|
Assert.AreEqual('123', ordinalValue.AsString, 'Ordinal AsString incorrect');
|
||||||
|
|
||||||
|
// Float
|
||||||
|
floatValue := TDataValue.FromFloat(45.67);
|
||||||
|
Assert.AreEqual(FloatToStr(45.67), floatValue.AsString, 'Float AsString incorrect');
|
||||||
|
|
||||||
|
// Text
|
||||||
|
textValue := TDataValue.FromText('Hello');
|
||||||
|
Assert.AreEqual('Hello', textValue.AsString, 'Text AsString incorrect');
|
||||||
|
|
||||||
|
// Timestamp
|
||||||
|
now := System.Sysutils.Now;
|
||||||
|
tsValue := TDataValue.FromTimestamp(now);
|
||||||
|
Assert.AreEqual(DateTimeToStr(now), tsValue.AsString, 'Timestamp AsString incorrect');
|
||||||
|
|
||||||
|
// Enum
|
||||||
|
colorType := TDataType.EnumOf('Color', ['Red', 'Green', 'Blue']);
|
||||||
|
enumValue := colorType.CreateValue('Green');
|
||||||
|
Assert.AreEqual('Green', enumValue.AsString, 'Enum AsString incorrect');
|
||||||
|
|
||||||
|
// Array
|
||||||
|
intArrayType := TDataType.ArrayOfType(TDataType.Ordinal);
|
||||||
|
arrayValue := intArrayType.CreateValue([TDataValue.FromOrdinal(1), TDataValue.FromOrdinal(2)]);
|
||||||
|
Assert.AreEqual('[1, 2]', arrayValue.AsString, 'Array AsString incorrect');
|
||||||
|
|
||||||
|
// Record
|
||||||
|
personType := TDataType.RecordOf([TRecordField.Create('ID', TDataType.Ordinal), TRecordField.Create('Name', TDataType.Text)]);
|
||||||
|
recordValue := personType.CreateValue([TDataValue.FromOrdinal(1), TDataValue.FromText('Bob')]);
|
||||||
|
Assert.AreEqual('<ID: 1, Name: Bob>', recordValue.AsString, 'Record AsString incorrect');
|
||||||
|
|
||||||
|
// Tuple
|
||||||
|
tupleValue := TDataValue.FromTuple([TDataValue.FromOrdinal(10), TDataValue.FromText('Tuple')]);
|
||||||
|
Assert.AreEqual('(10, Tuple)', tupleValue.AsString, 'Tuple AsString incorrect');
|
||||||
|
end;
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
TDUnitX.RegisterTestFixture(TMyTestObject);
|
TDUnitX.RegisterTestFixture(TMyTestObject);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user