THRIFT-4862 better ToString() support for enums and container types
Client: Delphi
Patch: Jens Geyer

This closes #1795
diff --git a/lib/delphi/src/Thrift.Collections.pas b/lib/delphi/src/Thrift.Collections.pas
index b2206cb..2e13724 100644
--- a/lib/delphi/src/Thrift.Collections.pas
+++ b/lib/delphi/src/Thrift.Collections.pas
@@ -22,7 +22,7 @@
 interface
 
 uses
-  Generics.Collections, Generics.Defaults, Thrift.Utils;
+  SysUtils, Generics.Collections, Generics.Defaults, Thrift.Utils;
 
 type
 
@@ -30,11 +30,11 @@
   TArray<T> = array of T;
 {$IFEND}
 
-  IThriftContainer = interface
-    ['{93DEF5A0-D162-461A-AB22-5B4EE0734050}']
-    function ToString: string;
+  IThriftContainer = interface( ISupportsToString)
+    ['{E05C0F9D-A4F5-491D-AADA-C926B4BDB6E4}']
   end;
 
+
   IThriftDictionary<TKey,TValue> = interface(IThriftContainer)
     ['{25EDD506-F9D1-4008-A40F-5940364B7E46}']
     function GetEnumerator: TEnumerator<TPair<TKey,TValue>>;
@@ -64,7 +64,7 @@
     property Values: TDictionary<TKey,TValue>.TValueCollection read GetValues;
   end;
 
-  TThriftDictionaryImpl<TKey,TValue> = class( TInterfacedObject, IThriftDictionary<TKey,TValue>)
+  TThriftDictionaryImpl<TKey,TValue> = class( TInterfacedObject, IThriftDictionary<TKey,TValue>, IThriftContainer, ISupportsToString)
   private
     FDictionaly : TDictionary<TKey,TValue>;
   protected
@@ -95,6 +95,7 @@
   public
     constructor Create(ACapacity: Integer = 0);
     destructor Destroy; override;
+    function ToString : string;  override;
   end;
 
   IThriftList<T> = interface(IThriftContainer)
@@ -140,7 +141,7 @@
     property Items[Index: Integer]: T read GetItem write SetItem; default;
   end;
 
-  TThriftListImpl<T> = class( TInterfacedObject, IThriftList<T>)
+  TThriftListImpl<T> = class( TInterfacedObject, IThriftList<T>, IThriftContainer, ISupportsToString)
   private
     FList : TList<T>;
   protected
@@ -186,6 +187,7 @@
   public
     constructor Create;
     destructor Destroy; override;
+    function ToString : string;  override;
   end;
 
   IHashSet<TValue> = interface(IThriftContainer)
@@ -202,7 +204,7 @@
     function Remove( const item: TValue ): Boolean;
   end;
 
-  THashSetImpl<TValue> = class( TInterfacedObject, IHashSet<TValue>)
+  THashSetImpl<TValue> = class( TInterfacedObject, IHashSet<TValue>, IThriftContainer, ISupportsToString)
   private
     FDictionary : IThriftDictionary<TValue,Integer>;
     FIsReadOnly: Boolean;
@@ -219,6 +221,7 @@
     function Remove( const item: TValue ): Boolean;
   public
     constructor Create;
+    function ToString : string;  override;
   end;
 
 implementation
@@ -287,6 +290,28 @@
   end;
 end;
 
+function THashSetImpl<TValue>.ToString : string;
+var elm : TValue;
+    sb : TThriftStringBuilder;
+    first : Boolean;
+begin
+  sb := TThriftStringBuilder.Create('{');
+  try
+    first := TRUE;
+    for elm in FDictionary.Keys do begin
+      if first
+      then first := FALSE
+      else sb.Append(', ');
+
+      sb.Append( StringUtils<TValue>.ToString(elm));
+    end;
+    sb.Append('}');
+    Result := sb.ToString;
+  finally
+    sb.Free;
+  end;
+end;
+
 { TThriftDictionaryImpl<TKey, TValue> }
 
 procedure TThriftDictionaryImpl<TKey, TValue>.Add(const Key: TKey;
@@ -393,6 +418,32 @@
 {$IFEND}
 end;
 
+function TThriftDictionaryImpl<TKey, TValue>.ToString : string;
+var pair : TPair<TKey, TValue>;
+    sb : TThriftStringBuilder;
+    first : Boolean;
+begin
+  sb := TThriftStringBuilder.Create('{');
+  try
+    first := TRUE;
+    for pair in FDictionaly do begin
+      if first
+      then first := FALSE
+      else sb.Append(', ');
+
+      sb.Append( '(');
+      sb.Append( StringUtils<TKey>.ToString(pair.Key));
+      sb.Append(' => ');
+      sb.Append( StringUtils<TValue>.ToString(pair.Value));
+      sb.Append(')');
+    end;
+    sb.Append('}');
+    Result := sb.ToString;
+  finally
+    sb.Free;
+  end;
+end;
+
 procedure TThriftDictionaryImpl<TKey, TValue>.TrimExcess;
 begin
   FDictionaly.TrimExcess;
@@ -611,6 +662,28 @@
 {$IFEND}
 end;
 
+function TThriftListImpl<T>.ToString : string;
+var elm : T;
+    sb : TThriftStringBuilder;
+    first : Boolean;
+begin
+  sb := TThriftStringBuilder.Create('{');
+  try
+    first := TRUE;
+    for elm in FList do begin
+      if first
+      then first := FALSE
+      else sb.Append(', ');
+
+      sb.Append( StringUtils<T>.ToString(elm));
+    end;
+    sb.Append('}');
+    Result := sb.ToString;
+  finally
+    sb.Free;
+  end;
+end;
+
 procedure TThriftListImpl<T>.TrimExcess;
 begin
   FList.TrimExcess;