Our initial implementation of assets was intentionally naive, because they were limited to single-file assets. However, it turns out that for real scenarios (like lambdas), we want to support multi-file assets. In this change, we introduce the concept of an Archive. An archive is what the term classically means: a collection of files, addressed as one. For now, we support three kinds: tarfile archives (*.tar), gzip-compressed tarfile archives (*.tgz, *.tar), and normal zipfile archives (*.zip). There is a fair bit of library support for manipulating Archives as a logical collection of Assets. I've gone to great length to avoid making copies, however, sometimes it is unavoidable (for example, when sizes are required in order to emit offsets). This is also complicated by the fact that the AWS libraries often want seekable streams, if not actual raw contiguous []byte slices.
101 lines
2.6 KiB
Go
101 lines
2.6 KiB
Go
// Copyright 2017 Pulumi, Inc. All rights reserved.
|
|
|
|
package cidlc
|
|
|
|
import (
|
|
"go/types"
|
|
"reflect"
|
|
|
|
"github.com/pulumi/coconut/pkg/resource/idl"
|
|
"github.com/pulumi/coconut/pkg/util/contract"
|
|
)
|
|
|
|
func IsPrimitive(t types.Type) bool {
|
|
if basic, isbasic := t.(*types.Basic); isbasic {
|
|
switch basic.Kind() {
|
|
case types.Bool, types.Float64, types.String:
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// IsEntity checks whether a type is an entity that can be used by-reference (asset, resource, etc).
|
|
func IsEntity(obj *types.TypeName, t types.Type) bool {
|
|
if res, _ := IsResource(obj, t); res {
|
|
return true
|
|
}
|
|
spec, _ := IsSpecial(obj)
|
|
return spec
|
|
}
|
|
|
|
// IsResource checks whether a type is a special IDL resource. If yes, it returns true for the first boolean, and the
|
|
// second boolean indicates whether the resource is named or not.
|
|
func IsResource(obj *types.TypeName, t types.Type) (bool, bool) {
|
|
contract.Assert(obj != nil)
|
|
|
|
// If this is a resource type itself, then we're done.
|
|
if isres, isname := IsSpecialResource(obj); isres {
|
|
return isres, isname
|
|
}
|
|
|
|
// If a named type, fetch the underlying.
|
|
if n, is := t.(*types.Named); is {
|
|
t = n.Underlying()
|
|
}
|
|
|
|
if s, is := t.(*types.Struct); is {
|
|
// Otherwise, it's a resource if it has an embedded resource field.
|
|
for i := 0; i < s.NumFields(); i++ {
|
|
fld := s.Field(i)
|
|
if fld.Anonymous() {
|
|
if named, ok := fld.Type().(*types.Named); ok {
|
|
if isres, isname := IsSpecialResource(named.Obj()); isres {
|
|
return isres, isname
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false, false
|
|
}
|
|
|
|
type SpecialType int
|
|
|
|
const (
|
|
NotSpecialType = iota
|
|
SpecialResourceType
|
|
SpecialNamedResourceType
|
|
SpecialAssetType
|
|
SpecialArchiveType
|
|
)
|
|
|
|
var (
|
|
idlArchiveType = reflect.TypeOf(idl.Archive{})
|
|
idlAssetType = reflect.TypeOf(idl.Asset{})
|
|
idlResourceType = reflect.TypeOf(idl.Resource{})
|
|
idlNamedResourceType = reflect.TypeOf(idl.NamedResource{})
|
|
)
|
|
|
|
func IsSpecial(obj *types.TypeName) (bool, SpecialType) {
|
|
if obj != nil && obj.Pkg().Path() == idlResourceType.PkgPath() {
|
|
switch obj.Name() {
|
|
case idlArchiveType.Name():
|
|
return true, SpecialArchiveType
|
|
case idlAssetType.Name():
|
|
return true, SpecialAssetType
|
|
case idlResourceType.Name():
|
|
return true, SpecialResourceType
|
|
case idlNamedResourceType.Name():
|
|
return true, SpecialNamedResourceType
|
|
}
|
|
}
|
|
return false, NotSpecialType
|
|
}
|
|
|
|
func IsSpecialResource(obj *types.TypeName) (bool, bool) {
|
|
spec, kind := IsSpecial(obj)
|
|
isres := (spec && kind == SpecialResourceType)
|
|
isnamed := (spec && kind == SpecialNamedResourceType)
|
|
return isres || isnamed, isnamed
|
|
}
|