blob: 778fc3b6c9fb31da7b094ee60c1d5ac263a432c1 [file] [log] [blame]
/*
* 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)
}