Skip to content

Commit

Permalink
vam: len() function
Browse files Browse the repository at this point in the history
  • Loading branch information
mattnibs committed Aug 23, 2024
1 parent 79ea93b commit a98b822
Show file tree
Hide file tree
Showing 8 changed files with 267 additions and 9 deletions.
18 changes: 9 additions & 9 deletions runtime/sam/expr/function/len.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ type LenFn struct {
}

func (l *LenFn) Call(ectx expr.Context, args []zed.Value) zed.Value {
val := args[0]
val := args[0].Under(ectx.Arena())
var length int
switch typ := zed.TypeUnder(args[0].Type()).(type) {
switch typ := zed.TypeUnder(val.Type()).(type) {
case *zed.TypeOfNull:
case *zed.TypeRecord:
length = len(typ.Fields)
Expand All @@ -32,31 +32,31 @@ func (l *LenFn) Call(ectx expr.Context, args []zed.Value) zed.Value {
if err != nil {
return l.zctx.NewError(ectx.Arena(), err)
}
length = typeLength(t)
length = TypeLength(t)
default:
return l.zctx.WrapError(ectx.Arena(), "len: bad type", val)
}
return zed.NewInt64(int64(length))
}

func typeLength(typ zed.Type) int {
func TypeLength(typ zed.Type) int {
switch typ := typ.(type) {
case *zed.TypeNamed:
return typeLength(typ.Type)
return TypeLength(typ.Type)
case *zed.TypeRecord:
return len(typ.Fields)
case *zed.TypeUnion:
return len(typ.Types)
case *zed.TypeSet:
return typeLength(typ.Type)
return TypeLength(typ.Type)
case *zed.TypeArray:
return typeLength(typ.Type)
return TypeLength(typ.Type)
case *zed.TypeEnum:
return len(typ.Symbols)
case *zed.TypeMap:
return typeLength(typ.ValType)
return TypeLength(typ.ValType)
case *zed.TypeError:
return typeLength(typ.Type)
return TypeLength(typ.Type)
default:
// Primitive type
return 1
Expand Down
2 changes: 2 additions & 0 deletions runtime/vam/expr/function/function.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ func New(zctx *zed.Context, name string, narg int) (expr.Function, field.Path, e
case "join":
argmax = 2
f = &Join{zctx: zctx}
case "len":
f = &Len{zctx}
case "levenshtein":
argmin, argmax = 2, 2
f = &Levenshtein{zctx}
Expand Down
75 changes: 75 additions & 0 deletions runtime/vam/expr/function/len.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package function

import (
"github.com/brimdata/zed"
"github.com/brimdata/zed/runtime/sam/expr/function"
"github.com/brimdata/zed/vector"
)

// https://github.com/brimdata/zed/blob/main/docs/language/functions.md#len
type Len struct {
zctx *zed.Context
}

func (l *Len) Call(args []vector.Any) vector.Any {
val := vector.Under(args[0])
out := vector.NewIntEmpty(zed.TypeInt64, val.Len(), nil)
switch typ := val.Type().(type) {
case *zed.TypeOfNull:
return vector.NewConst(nil, zed.NewInt64(0), val.Len(), nil)
case *zed.TypeRecord:
length := int64(len(typ.Fields))
return vector.NewConst(nil, zed.NewInt64(length), val.Len(), nil)
case *zed.TypeArray, *zed.TypeSet, *zed.TypeMap:
for i := uint32(0); i < val.Len(); i++ {
start, end, _ := vector.ContainerOffset(val, i)
out.Append(int64(end) - int64(start))
}
case *zed.TypeOfString:
for i := uint32(0); i < val.Len(); i++ {
s, _ := vector.StringValue(val, i)
out.Append(int64(len(s)))
}
case *zed.TypeOfBytes:
for i := uint32(0); i < val.Len(); i++ {
s, _ := vector.BytesValue(val, i)
out.Append(int64(len(s)))
}
case *zed.TypeOfIP:
for i := uint32(0); i < val.Len(); i++ {
ip, null := vector.IPValue(val, i)
if null {
out.Append(0)
continue
}
out.Append(int64(len(ip.AsSlice())))
}
case *zed.TypeOfNet:
for i := uint32(0); i < val.Len(); i++ {
n, null := vector.NetValue(val, i)
if null {
out.Append(0)
continue
}
out.Append(int64(len(zed.AppendNet(nil, n))))
}
case *zed.TypeError:
return vector.NewWrappedError(l.zctx, "len()", val)
case *zed.TypeOfType:
for i := uint32(0); i < val.Len(); i++ {
v, null := vector.TypeValueValue(val, i)
if null {
out.Append(0)
continue
}
t, err := l.zctx.LookupByValue(v)
if err != nil {
panic(err)
}
out.Append(int64(function.TypeLength(t)))
}
default:
return vector.NewWrappedError(l.zctx, "len: bad type", val)
}
return out
}
89 changes: 89 additions & 0 deletions runtime/ztests/expr/function/len.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
zed: len(a)

vector: true

input: |
{a:null}
{a:null(bytes)}
{a:0x}
{a:0x0123}
{a:0x0123((bytes,string))}
{a:null(string)}
{a:""}
{a:"string"}
{a:null(ip)}
{a:1.0.0.0}
{a:1::}
{a:null(net)}
{a:1.0.0.0/8}
{a:1::/8}
{a:null({})}
{a:{}}
{a:{x:1}}
{a:{x:1,s:"hello"}}
{a:{x:{a:1,b:2}}}
{a:null([int64])}
{a:[]([int64])}
{a:[1,2]([int64])}
{a:null(|[int64]|)}
{a:|[]|(|[int64]|)}
{a:|[1,2]|(|[int64]|)}
{a:null(|{int64:int64}|)}
{a:|{1:1}|(|{int64:int64}|)}
{a:|{1:1,2:2}|}
{a:<int64>}
{a:<type>}
{a:<{x:int64,y:int64}>}
{a:<(int64,string)>}
{a:<[int64]>}
{a:<[(int64,string)]>}
{a:<any=(int64,string)>}
# XXX Currently vcache doesn't support loading errors, add these values when
# this is fixed.
# {a:error(null)}
# {a:error("")}
# {a:error("error")}

output: |
0
0
0
2
2
0
0
6
0
4
16
0
8
32
0
0
1
2
1
0
0
2
0
0
2
0
1
2
1
1
2
2
1
2
2
# XXX Currently vcache doesn't support loading errors, add these values when
# this is fixed.
# error({message:"len()",on:null(error(null))})
# error({message:"len()",on:error("")})
# error({message:"len()",on:error("error")})
23 changes: 23 additions & 0 deletions vector/bytes.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,26 @@ func (b *Bytes) Value(slot uint32) []byte {
}
return b.Bytes[b.Offs[slot]:b.Offs[slot+1]]
}

func BytesValue(val Any, slot uint32) ([]byte, bool) {
switch val := val.(type) {
case *Bytes:
return val.Value(slot), val.Nulls.Value(slot)
case *Const:
if val.Nulls.Value(slot) {
return nil, true
}
s, _ := val.AsBytes()
return s, false
case *Dict:
if val.Nulls.Value(slot) {
return nil, true
}
slot = uint32(val.Index[slot])
return val.Any.(*Bytes).Value(slot), false
case *View:
slot = val.Index[slot]
return BytesValue(val.Any, slot)
}
panic(val)
}
23 changes: 23 additions & 0 deletions vector/ip.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,26 @@ func (i *IP) Serialize(b *zcode.Builder, slot uint32) {
b.Append(zed.EncodeIP(i.Values[slot]))
}
}

func IPValue(val Any, slot uint32) (netip.Addr, bool) {
switch val := val.(type) {
case *IP:
return val.Values[slot], val.Nulls.Value(slot)
case *Const:
if val.Nulls.Value(slot) {
return netip.Addr{}, true
}
b, _ := val.AsBytes()
return zed.DecodeIP(b), false
case *Dict:
if val.Nulls.Value(slot) {
return netip.Addr{}, true
}
slot = uint32(val.Index[slot])
return val.Any.(*IP).Values[slot], false
case *View:
slot = val.Index[slot]
return IPValue(val.Any, slot)
}
panic(val)
}
23 changes: 23 additions & 0 deletions vector/net.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,26 @@ func (n *Net) Serialize(b *zcode.Builder, slot uint32) {
b.Append(zed.EncodeNet(n.Values[slot]))
}
}

func NetValue(val Any, slot uint32) (netip.Prefix, bool) {
switch val := val.(type) {
case *Net:
return val.Values[slot], val.Nulls.Value(slot)
case *Const:
if val.Nulls.Value(slot) {
return netip.Prefix{}, true
}
s, _ := val.AsBytes()
return zed.DecodeNet(s), false
case *Dict:
if val.Nulls.Value(slot) {
return netip.Prefix{}, true
}
slot = uint32(val.Index[slot])
return val.Any.(*Net).Values[slot], false
case *View:
slot = val.Index[slot]
return NetValue(val.Any, slot)
}
panic(val)
}
23 changes: 23 additions & 0 deletions vector/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,26 @@ func (t *TypeValue) Serialize(b *zcode.Builder, slot uint32) {
b.Append(t.Value(slot))
}
}

func TypeValueValue(val Any, slot uint32) ([]byte, bool) {
switch val := val.(type) {
case *TypeValue:
return val.Value(slot), val.Nulls.Value(slot)
case *Const:
if val.Nulls.Value(slot) {
return nil, true
}
s, _ := val.AsBytes()
return s, false
case *Dict:
if val.Nulls.Value(slot) {
return nil, true
}
slot = uint32(val.Index[slot])
return val.Any.(*TypeValue).Value(slot), false
case *View:
slot = val.Index[slot]
return TypeValueValue(val.Any, slot)
}
panic(val)
}

0 comments on commit a98b822

Please sign in to comment.