THRIFT-625: Add support for 'Go'; provided by Aalok Shah.



git-svn-id: https://svn.apache.org/repos/asf/thrift/trunk@1072478 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/go/thrift/tlist.go b/lib/go/thrift/tlist.go
new file mode 100644
index 0000000..778fc3b
--- /dev/null
+++ b/lib/go/thrift/tlist.go
@@ -0,0 +1,222 @@
+/*
+ * 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.
+ */
+
+package thrift
+
+import (
+  "container/vector"
+)
+
+/**
+ * Helper class that encapsulates list metadata.
+ *
+ */
+type TList interface {
+  TContainer
+  ElemType() TType
+  At(i int) interface{}
+  Set(i int, data interface{})
+  Push(data interface{})
+  Pop() interface{}
+  Swap(i, j int)
+  Insert(i int, data interface{})
+  Delete(i int)
+  Less(i, j int) bool
+  Iter() <-chan interface{}
+}
+
+type tList struct {
+  elemType TType
+  l        *vector.Vector
+}
+
+func NewTList(t TType, s int) TList {
+  var v vector.Vector
+  return &tList{elemType: t, l: v.Resize(s, s)}
+}
+
+func NewTListDefault() TList {
+  var v vector.Vector
+  return &tList{elemType: TType(STOP), l: &v}
+}
+
+func (p *tList) ElemType() TType {
+  return p.elemType
+}
+
+func (p *tList) Len() int {
+  return p.l.Len()
+}
+
+func (p *tList) At(i int) interface{} {
+  return p.l.At(i)
+}
+
+func (p *tList) Set(i int, data interface{}) {
+  if p.elemType.IsEmptyType() {
+    p.elemType = TypeFromValue(data)
+  }
+  if data, ok := p.elemType.CoerceData(data); ok {
+    p.l.Set(i, data)
+  }
+}
+
+func (p *tList) Push(data interface{}) {
+  if p.elemType.IsEmptyType() {
+    p.elemType = TypeFromValue(data)
+  }
+  data, ok := p.elemType.CoerceData(data)
+  if ok {
+    p.l.Push(data)
+  }
+}
+
+func (p *tList) Pop() interface{} {
+  return p.l.Pop()
+}
+
+func (p *tList) Swap(i, j int) {
+  p.l.Swap(i, j)
+}
+
+func (p *tList) Insert(i int, data interface{}) {
+  p.l.Insert(i, data)
+}
+
+func (p *tList) Delete(i int) {
+  p.l.Delete(i)
+}
+
+func (p *tList) Contains(data interface{}) bool {
+  return p.indexOf(data) >= 0
+}
+
+func (p *tList) Less(i, j int) bool {
+  return p.l.Less(i, j)
+}
+
+func (p *tList) Iter() <-chan interface{} {
+  c := make(chan interface{})
+  go p.iterate(c)
+  return c
+}
+
+func (p *tList) iterate(c chan<- interface{}) {
+  for _, elem := range *p.l {
+    c <- elem
+  }
+  close(c)
+}
+
+func (p *tList) indexOf(data interface{}) int {
+  if data == nil {
+    size := p.l.Len()
+    for i := 0; i < size; i++ {
+      if p.l.At(i) == nil {
+        return i
+      }
+    }
+    return -1
+  }
+  data, ok := p.elemType.CoerceData(data)
+  if data == nil || !ok {
+    return -1
+  }
+  size := p.l.Len()
+  if p.elemType.IsBaseType() || p.elemType.IsEnum() {
+    for i := 0; i < size; i++ {
+      if data == p.l.At(i) {
+        return i
+      }
+    }
+    return -1
+  }
+  if cmp, ok := data.(EqualsOtherInterface); ok {
+    for i := 0; i < size; i++ {
+      if cmp.Equals(p.l.At(i)) {
+        return i
+      }
+    }
+    return -1
+  }
+  switch p.elemType {
+  case MAP:
+    if cmp, ok := data.(EqualsMap); ok {
+      for i := 0; i < size; i++ {
+        v := p.l.At(i)
+        if v == nil {
+          continue
+        }
+        if cmp.Equals(v.(TMap)) {
+          return i
+        }
+      }
+      return -1
+    }
+  case SET:
+    if cmp, ok := data.(EqualsSet); ok {
+      for i := 0; i < size; i++ {
+        v := p.l.At(i)
+        if v == nil {
+          continue
+        }
+        if cmp.Equals(v.(TSet)) {
+          return i
+        }
+      }
+      return -1
+    }
+  case LIST:
+    if cmp, ok := data.(EqualsList); ok {
+      for i := 0; i < size; i++ {
+        v := p.l.At(i)
+        if v == nil {
+          continue
+        }
+        if cmp.Equals(v.(TList)) {
+          return i
+        }
+      }
+      return -1
+    }
+  case STRUCT:
+    if cmp, ok := data.(EqualsStruct); ok {
+      for i := 0; i < size; i++ {
+        v := p.l.At(i)
+        if v == nil {
+          continue
+        }
+        if cmp.Equals(v.(TStruct)) {
+          return i
+        }
+      }
+      return -1
+    }
+  }
+  return -1
+}
+
+func (p *tList) Equals(other interface{}) bool {
+  c, cok := p.CompareTo(other)
+  return cok && c == 0
+}
+
+func (p *tList) CompareTo(other interface{}) (int, bool) {
+  return TType(LIST).Compare(p, other)
+}