| /* | 
 |  * 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) | 
 | } |