mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 11:21:47 +00:00
Update aws-sdk-go: v1.0.7 -> v1.0.8
Adds support for the ap-northeast-2 (Seoul) region
This commit is contained in:
parent
bb3f5b1768
commit
430cf60b0f
104
Godeps/Godeps.json
generated
104
Godeps/Godeps.json
generated
@ -71,133 +71,133 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/awserr",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/awsutil",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/client",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/client/metadata",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/corehandlers",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/credentials",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/defaults",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/ec2metadata",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/request",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/session",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/endpoints",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/ec2query",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/json/jsonutil",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/jsonrpc",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/query",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/query/queryutil",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/rest",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/signer/v4",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/waiter",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/service/autoscaling",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/service/ec2",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/service/ecr",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/service/elb",
|
||||
"Comment": "v1.0.7",
|
||||
"Rev": "bf2f8fe7f45e68017086d069498638893feddf64"
|
||||
"Comment": "v1.0.8",
|
||||
"Rev": "c924893c38ecc04b18d7aab8a7aa561cb8b4c4cc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/beorn7/perks/quantile",
|
||||
|
2
vendor/github.com/aws/aws-sdk-go/aws/client/client.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go/aws/client/client.go
generated
vendored
@ -108,7 +108,7 @@ const logRespMsg = `DEBUG: Response %s/%s Details:
|
||||
-----------------------------------------------------`
|
||||
|
||||
func logResponse(r *request.Request) {
|
||||
var msg = "no reponse data"
|
||||
var msg = "no response data"
|
||||
if r.HTTPResponse != nil {
|
||||
logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
|
||||
dumpedBody, _ := httputil.DumpResponse(r.HTTPResponse, logBody)
|
||||
|
2
vendor/github.com/aws/aws-sdk-go/aws/version.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go/aws/version.go
generated
vendored
@ -5,4 +5,4 @@ package aws
|
||||
const SDKName = "aws-sdk-go"
|
||||
|
||||
// SDKVersion is the version of this SDK
|
||||
const SDKVersion = "1.0.7"
|
||||
const SDKVersion = "1.0.8"
|
||||
|
3
vendor/github.com/aws/aws-sdk-go/private/endpoints/endpoints.json
generated
vendored
3
vendor/github.com/aws/aws-sdk-go/private/endpoints/endpoints.json
generated
vendored
@ -78,6 +78,9 @@
|
||||
"ap-northeast-1/s3": {
|
||||
"endpoint": "s3-{region}.amazonaws.com"
|
||||
},
|
||||
"ap-northeast-2/s3": {
|
||||
"endpoint": "s3-{region}.amazonaws.com"
|
||||
},
|
||||
"sa-east-1/s3": {
|
||||
"endpoint": "s3-{region}.amazonaws.com"
|
||||
},
|
||||
|
3
vendor/github.com/aws/aws-sdk-go/private/endpoints/endpoints_map.go
generated
vendored
3
vendor/github.com/aws/aws-sdk-go/private/endpoints/endpoints_map.go
generated
vendored
@ -57,6 +57,9 @@ var endpointsMap = endpointStruct{
|
||||
"ap-northeast-1/s3": {
|
||||
Endpoint: "s3-{region}.amazonaws.com",
|
||||
},
|
||||
"ap-northeast-2/s3": {
|
||||
Endpoint: "s3-{region}.amazonaws.com",
|
||||
},
|
||||
"ap-southeast-1/s3": {
|
||||
Endpoint: "s3-{region}.amazonaws.com",
|
||||
},
|
||||
|
2
vendor/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal.go
generated
vendored
@ -25,5 +25,5 @@ func Unmarshal(r *request.Request) {
|
||||
|
||||
// UnmarshalMeta unmarshals header response values for an AWS Query service.
|
||||
func UnmarshalMeta(r *request.Request) {
|
||||
// TODO implement unmarshaling of request IDs
|
||||
r.RequestID = r.HTTPResponse.Header.Get("X-Amzn-Requestid")
|
||||
}
|
||||
|
306
vendor/github.com/aws/aws-sdk-go/service/ec2/api.go
generated
vendored
306
vendor/github.com/aws/aws-sdk-go/service/ec2/api.go
generated
vendored
@ -1475,7 +1475,7 @@ func (c *EC2) CreateSecurityGroupRequest(input *CreateSecurityGroupInput) (req *
|
||||
//
|
||||
// EC2-Classic: You can have up to 500 security groups.
|
||||
//
|
||||
// EC2-VPC: You can create up to 100 security groups per VPC.
|
||||
// EC2-VPC: You can create up to 500 security groups per VPC.
|
||||
//
|
||||
// When you create a security group, you specify a friendly name of your choice.
|
||||
// You can have a security group for use in EC2-Classic with the same name as
|
||||
@ -3041,21 +3041,20 @@ func (c *EC2) DescribeIdFormatRequest(input *DescribeIdFormatInput) (req *reques
|
||||
return
|
||||
}
|
||||
|
||||
// Important: This command is reserved for future use, and is currently not
|
||||
// available for you to use.
|
||||
//
|
||||
// Describes the ID format settings for your resources, for example, to view
|
||||
// which resource types are enabled for longer IDs. This request only returns
|
||||
// information about resource types whose ID formats can be modified; it does
|
||||
// not return information about other resource types.
|
||||
// Describes the ID format settings for your resources on a per-region basis,
|
||||
// for example, to view which resource types are enabled for longer IDs. This
|
||||
// request only returns information about resource types whose ID formats can
|
||||
// be modified; it does not return information about other resource types.
|
||||
//
|
||||
// The following resource types support longer IDs: instance | reservation.
|
||||
//
|
||||
// These settings apply to the IAM user who makes the request; they do not
|
||||
// apply to the entire AWS account. By default, an IAM user defaults to the
|
||||
// same settings as the root user, unless they explicitly override the settings
|
||||
// by running the ModifyIdFormat command. These settings are applied on a per-region
|
||||
// basis.
|
||||
// by running the ModifyIdFormat command. Resources created with longer IDs
|
||||
// are visible to all IAM users, regardless of these settings and provided that
|
||||
// they have permission to use the relevant Describe command for the resource
|
||||
// type.
|
||||
func (c *EC2) DescribeIdFormat(input *DescribeIdFormatInput) (*DescribeIdFormatOutput, error) {
|
||||
req, out := c.DescribeIdFormatRequest(input)
|
||||
err := req.Send()
|
||||
@ -4452,6 +4451,39 @@ func (c *EC2) DescribeVpcClassicLink(input *DescribeVpcClassicLinkInput) (*Descr
|
||||
return out, err
|
||||
}
|
||||
|
||||
const opDescribeVpcClassicLinkDnsSupport = "DescribeVpcClassicLinkDnsSupport"
|
||||
|
||||
// DescribeVpcClassicLinkDnsSupportRequest generates a request for the DescribeVpcClassicLinkDnsSupport operation.
|
||||
func (c *EC2) DescribeVpcClassicLinkDnsSupportRequest(input *DescribeVpcClassicLinkDnsSupportInput) (req *request.Request, output *DescribeVpcClassicLinkDnsSupportOutput) {
|
||||
op := &request.Operation{
|
||||
Name: opDescribeVpcClassicLinkDnsSupport,
|
||||
HTTPMethod: "POST",
|
||||
HTTPPath: "/",
|
||||
}
|
||||
|
||||
if input == nil {
|
||||
input = &DescribeVpcClassicLinkDnsSupportInput{}
|
||||
}
|
||||
|
||||
req = c.newRequest(op, input, output)
|
||||
output = &DescribeVpcClassicLinkDnsSupportOutput{}
|
||||
req.Data = output
|
||||
return
|
||||
}
|
||||
|
||||
// Describes the ClassicLink DNS support status of one or more VPCs. If enabled,
|
||||
// the DNS hostname of a linked EC2-Classic instance resolves to its private
|
||||
// IP address when addressed from an instance in the VPC to which it's linked.
|
||||
// Similarly, the DNS hostname of an instance in a VPC resolves to its private
|
||||
// IP address when addressed from a linked EC2-Classic instance. For more information
|
||||
// about ClassicLink, see ClassicLink (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/vpc-classiclink.html)
|
||||
// in the Amazon Elastic Compute Cloud User Guide.
|
||||
func (c *EC2) DescribeVpcClassicLinkDnsSupport(input *DescribeVpcClassicLinkDnsSupportInput) (*DescribeVpcClassicLinkDnsSupportOutput, error) {
|
||||
req, out := c.DescribeVpcClassicLinkDnsSupportRequest(input)
|
||||
err := req.Send()
|
||||
return out, err
|
||||
}
|
||||
|
||||
const opDescribeVpcEndpointServices = "DescribeVpcEndpointServices"
|
||||
|
||||
// DescribeVpcEndpointServicesRequest generates a request for the DescribeVpcEndpointServices operation.
|
||||
@ -4837,6 +4869,37 @@ func (c *EC2) DisableVpcClassicLink(input *DisableVpcClassicLinkInput) (*Disable
|
||||
return out, err
|
||||
}
|
||||
|
||||
const opDisableVpcClassicLinkDnsSupport = "DisableVpcClassicLinkDnsSupport"
|
||||
|
||||
// DisableVpcClassicLinkDnsSupportRequest generates a request for the DisableVpcClassicLinkDnsSupport operation.
|
||||
func (c *EC2) DisableVpcClassicLinkDnsSupportRequest(input *DisableVpcClassicLinkDnsSupportInput) (req *request.Request, output *DisableVpcClassicLinkDnsSupportOutput) {
|
||||
op := &request.Operation{
|
||||
Name: opDisableVpcClassicLinkDnsSupport,
|
||||
HTTPMethod: "POST",
|
||||
HTTPPath: "/",
|
||||
}
|
||||
|
||||
if input == nil {
|
||||
input = &DisableVpcClassicLinkDnsSupportInput{}
|
||||
}
|
||||
|
||||
req = c.newRequest(op, input, output)
|
||||
output = &DisableVpcClassicLinkDnsSupportOutput{}
|
||||
req.Data = output
|
||||
return
|
||||
}
|
||||
|
||||
// Disables ClassicLink DNS support for a VPC. If disabled, DNS hostnames resolve
|
||||
// to public IP addresses when addressed between a linked EC2-Classic instance
|
||||
// and instances in the VPC to which it's linked. For more information about
|
||||
// ClassicLink, see ClassicLink (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/vpc-classiclink.html)
|
||||
// in the Amazon Elastic Compute Cloud User Guide.
|
||||
func (c *EC2) DisableVpcClassicLinkDnsSupport(input *DisableVpcClassicLinkDnsSupportInput) (*DisableVpcClassicLinkDnsSupportOutput, error) {
|
||||
req, out := c.DisableVpcClassicLinkDnsSupportRequest(input)
|
||||
err := req.Send()
|
||||
return out, err
|
||||
}
|
||||
|
||||
const opDisassociateAddress = "DisassociateAddress"
|
||||
|
||||
// DisassociateAddressRequest generates a request for the DisassociateAddress operation.
|
||||
@ -4993,6 +5056,39 @@ func (c *EC2) EnableVpcClassicLink(input *EnableVpcClassicLinkInput) (*EnableVpc
|
||||
return out, err
|
||||
}
|
||||
|
||||
const opEnableVpcClassicLinkDnsSupport = "EnableVpcClassicLinkDnsSupport"
|
||||
|
||||
// EnableVpcClassicLinkDnsSupportRequest generates a request for the EnableVpcClassicLinkDnsSupport operation.
|
||||
func (c *EC2) EnableVpcClassicLinkDnsSupportRequest(input *EnableVpcClassicLinkDnsSupportInput) (req *request.Request, output *EnableVpcClassicLinkDnsSupportOutput) {
|
||||
op := &request.Operation{
|
||||
Name: opEnableVpcClassicLinkDnsSupport,
|
||||
HTTPMethod: "POST",
|
||||
HTTPPath: "/",
|
||||
}
|
||||
|
||||
if input == nil {
|
||||
input = &EnableVpcClassicLinkDnsSupportInput{}
|
||||
}
|
||||
|
||||
req = c.newRequest(op, input, output)
|
||||
output = &EnableVpcClassicLinkDnsSupportOutput{}
|
||||
req.Data = output
|
||||
return
|
||||
}
|
||||
|
||||
// Enables a VPC to support DNS hostname resolution for ClassicLink. If enabled,
|
||||
// the DNS hostname of a linked EC2-Classic instance resolves to its private
|
||||
// IP address when addressed from an instance in the VPC to which it's linked.
|
||||
// Similarly, the DNS hostname of an instance in a VPC resolves to its private
|
||||
// IP address when addressed from a linked EC2-Classic instance. For more information
|
||||
// about ClassicLink, see ClassicLink (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/vpc-classiclink.html)
|
||||
// in the Amazon Elastic Compute Cloud User Guide.
|
||||
func (c *EC2) EnableVpcClassicLinkDnsSupport(input *EnableVpcClassicLinkDnsSupportInput) (*EnableVpcClassicLinkDnsSupportOutput, error) {
|
||||
req, out := c.EnableVpcClassicLinkDnsSupportRequest(input)
|
||||
err := req.Send()
|
||||
return out, err
|
||||
}
|
||||
|
||||
const opGetConsoleOutput = "GetConsoleOutput"
|
||||
|
||||
// GetConsoleOutputRequest generates a request for the GetConsoleOutput operation.
|
||||
@ -5284,17 +5380,17 @@ func (c *EC2) ModifyIdFormatRequest(input *ModifyIdFormatInput) (req *request.Re
|
||||
return
|
||||
}
|
||||
|
||||
// Important: This command is reserved for future use, and is currently not
|
||||
// available for you to use.
|
||||
//
|
||||
// Modifies the ID format for the specified resource. You can specify that
|
||||
// resources should receive longer IDs (17-character IDs) when they are created.
|
||||
// The following resource types support longer IDs: instance | reservation.
|
||||
// Modifies the ID format for the specified resource on a per-region basis.
|
||||
// You can specify that resources should receive longer IDs (17-character IDs)
|
||||
// when they are created. The following resource types support longer IDs: instance
|
||||
// | reservation.
|
||||
//
|
||||
// This setting applies to the IAM user who makes the request; it does not
|
||||
// apply to the entire AWS account. By default, an IAM user defaults to the
|
||||
// same settings as the root user, unless they explicitly override the settings
|
||||
// by running this request. These settings are applied on a per-region basis.
|
||||
// by running this request. Resources created with longer IDs are visible to
|
||||
// all IAM users, regardless of these settings and provided that they have permission
|
||||
// to use the relevant Describe command for the resource type.
|
||||
func (c *EC2) ModifyIdFormat(input *ModifyIdFormatInput) (*ModifyIdFormatOutput, error) {
|
||||
req, out := c.ModifyIdFormatRequest(input)
|
||||
err := req.Send()
|
||||
@ -5722,12 +5818,14 @@ func (c *EC2) MoveAddressToVpcRequest(input *MoveAddressToVpcInput) (req *reques
|
||||
}
|
||||
|
||||
// Moves an Elastic IP address from the EC2-Classic platform to the EC2-VPC
|
||||
// platform. The Elastic IP address must be allocated to your account, and it
|
||||
// must not be associated with an instance. After the Elastic IP address is
|
||||
// moved, it is no longer available for use in the EC2-Classic platform, unless
|
||||
// you move it back using the RestoreAddressToClassic request. You cannot move
|
||||
// an Elastic IP address that's allocated for use in the EC2-VPC platform to
|
||||
// the EC2-Classic platform.
|
||||
// platform. The Elastic IP address must be allocated to your account for more
|
||||
// than 24 hours, and it must not be associated with an instance. After the
|
||||
// Elastic IP address is moved, it is no longer available for use in the EC2-Classic
|
||||
// platform, unless you move it back using the RestoreAddressToClassic request.
|
||||
// You cannot move an Elastic IP address that's allocated for use in the EC2-VPC
|
||||
// platform to the EC2-Classic platform. You cannot migrate an Elastic IP address
|
||||
// that's associated with a reverse DNS record. Contact AWS account and billing
|
||||
// support to remove the reverse DNS record.
|
||||
func (c *EC2) MoveAddressToVpc(input *MoveAddressToVpcInput) (*MoveAddressToVpcOutput, error) {
|
||||
req, out := c.MoveAddressToVpcRequest(input)
|
||||
err := req.Send()
|
||||
@ -6358,7 +6456,9 @@ func (c *EC2) RestoreAddressToClassicRequest(input *RestoreAddressToClassicInput
|
||||
// Restores an Elastic IP address that was previously moved to the EC2-VPC platform
|
||||
// back to the EC2-Classic platform. You cannot move an Elastic IP address that
|
||||
// was originally allocated for use in EC2-VPC. The Elastic IP address must
|
||||
// not be associated with an instance or network interface.
|
||||
// not be associated with an instance or network interface. You cannot restore
|
||||
// an Elastic IP address that's associated with a reverse DNS record. Contact
|
||||
// AWS account and billing support to remove the reverse DNS record.
|
||||
func (c *EC2) RestoreAddressToClassic(input *RestoreAddressToClassicInput) (*RestoreAddressToClassicOutput, error) {
|
||||
req, out := c.RestoreAddressToClassicRequest(input)
|
||||
err := req.Send()
|
||||
@ -8147,6 +8247,27 @@ func (s CancelledSpotInstanceRequest) GoString() string {
|
||||
return s.String()
|
||||
}
|
||||
|
||||
// Describes the ClassicLink DNS support status of a VPC.
|
||||
type ClassicLinkDnsSupport struct {
|
||||
_ struct{} `type:"structure"`
|
||||
|
||||
// Indicates whether ClassicLink DNS support is enabled for the VPC.
|
||||
ClassicLinkDnsSupported *bool `locationName:"classicLinkDnsSupported" type:"boolean"`
|
||||
|
||||
// The ID of the VPC.
|
||||
VpcId *string `locationName:"vpcId" type:"string"`
|
||||
}
|
||||
|
||||
// String returns the string representation
|
||||
func (s ClassicLinkDnsSupport) String() string {
|
||||
return awsutil.Prettify(s)
|
||||
}
|
||||
|
||||
// GoString returns the string representation
|
||||
func (s ClassicLinkDnsSupport) GoString() string {
|
||||
return s.String()
|
||||
}
|
||||
|
||||
// Describes a linked EC2-Classic instance.
|
||||
type ClassicLinkInstance struct {
|
||||
_ struct{} `type:"structure"`
|
||||
@ -12146,7 +12267,7 @@ type DescribeInstancesInput struct {
|
||||
//
|
||||
// network-interface.mac-address - The MAC address of the network interface.
|
||||
//
|
||||
// network-interface-private-dns-name - The private DNS name of the network
|
||||
// network-interface.private-dns-name - The private DNS name of the network
|
||||
// interface.
|
||||
//
|
||||
// network-interface.source-dest-check - Whether the network interface performs
|
||||
@ -14552,6 +14673,52 @@ func (s DescribeVpcAttributeOutput) GoString() string {
|
||||
return s.String()
|
||||
}
|
||||
|
||||
type DescribeVpcClassicLinkDnsSupportInput struct {
|
||||
_ struct{} `type:"structure"`
|
||||
|
||||
// The maximum number of items to return for this request. The request returns
|
||||
// a token that you can specify in a subsequent call to get the next set of
|
||||
// results.
|
||||
MaxResults *int64 `locationName:"maxResults" min:"5" type:"integer"`
|
||||
|
||||
// The token for the next set of items to return. (You received this token from
|
||||
// a prior call.)
|
||||
NextToken *string `locationName:"nextToken" min:"1" type:"string"`
|
||||
|
||||
// One or more VPC IDs.
|
||||
VpcIds []*string `locationNameList:"VpcId" type:"list"`
|
||||
}
|
||||
|
||||
// String returns the string representation
|
||||
func (s DescribeVpcClassicLinkDnsSupportInput) String() string {
|
||||
return awsutil.Prettify(s)
|
||||
}
|
||||
|
||||
// GoString returns the string representation
|
||||
func (s DescribeVpcClassicLinkDnsSupportInput) GoString() string {
|
||||
return s.String()
|
||||
}
|
||||
|
||||
type DescribeVpcClassicLinkDnsSupportOutput struct {
|
||||
_ struct{} `type:"structure"`
|
||||
|
||||
// The token to use when requesting the next set of items.
|
||||
NextToken *string `locationName:"nextToken" min:"1" type:"string"`
|
||||
|
||||
// Information about the ClassicLink DNS support status of the VPCs.
|
||||
Vpcs []*ClassicLinkDnsSupport `locationName:"vpcs" locationNameList:"item" type:"list"`
|
||||
}
|
||||
|
||||
// String returns the string representation
|
||||
func (s DescribeVpcClassicLinkDnsSupportOutput) String() string {
|
||||
return awsutil.Prettify(s)
|
||||
}
|
||||
|
||||
// GoString returns the string representation
|
||||
func (s DescribeVpcClassicLinkDnsSupportOutput) GoString() string {
|
||||
return s.String()
|
||||
}
|
||||
|
||||
type DescribeVpcClassicLinkInput struct {
|
||||
_ struct{} `type:"structure"`
|
||||
|
||||
@ -14979,7 +15146,8 @@ type DescribeVpnGatewaysInput struct {
|
||||
//
|
||||
// attachment.vpc-id - The ID of an attached VPC.
|
||||
//
|
||||
// availability-zone - The Availability Zone for the virtual private gateway.
|
||||
// availability-zone - The Availability Zone for the virtual private gateway
|
||||
// (if applicable).
|
||||
//
|
||||
// state - The state of the virtual private gateway (pending | available
|
||||
// | deleting | deleted).
|
||||
@ -15315,6 +15483,40 @@ func (s DisableVgwRoutePropagationOutput) GoString() string {
|
||||
return s.String()
|
||||
}
|
||||
|
||||
type DisableVpcClassicLinkDnsSupportInput struct {
|
||||
_ struct{} `type:"structure"`
|
||||
|
||||
// The ID of the VPC.
|
||||
VpcId *string `type:"string"`
|
||||
}
|
||||
|
||||
// String returns the string representation
|
||||
func (s DisableVpcClassicLinkDnsSupportInput) String() string {
|
||||
return awsutil.Prettify(s)
|
||||
}
|
||||
|
||||
// GoString returns the string representation
|
||||
func (s DisableVpcClassicLinkDnsSupportInput) GoString() string {
|
||||
return s.String()
|
||||
}
|
||||
|
||||
type DisableVpcClassicLinkDnsSupportOutput struct {
|
||||
_ struct{} `type:"structure"`
|
||||
|
||||
// Returns true if the request succeeds; otherwise, it returns an error.
|
||||
Return *bool `locationName:"return" type:"boolean"`
|
||||
}
|
||||
|
||||
// String returns the string representation
|
||||
func (s DisableVpcClassicLinkDnsSupportOutput) String() string {
|
||||
return awsutil.Prettify(s)
|
||||
}
|
||||
|
||||
// GoString returns the string representation
|
||||
func (s DisableVpcClassicLinkDnsSupportOutput) GoString() string {
|
||||
return s.String()
|
||||
}
|
||||
|
||||
type DisableVpcClassicLinkInput struct {
|
||||
_ struct{} `type:"structure"`
|
||||
|
||||
@ -15711,6 +15913,40 @@ func (s EnableVolumeIOOutput) GoString() string {
|
||||
return s.String()
|
||||
}
|
||||
|
||||
type EnableVpcClassicLinkDnsSupportInput struct {
|
||||
_ struct{} `type:"structure"`
|
||||
|
||||
// The ID of the VPC.
|
||||
VpcId *string `type:"string"`
|
||||
}
|
||||
|
||||
// String returns the string representation
|
||||
func (s EnableVpcClassicLinkDnsSupportInput) String() string {
|
||||
return awsutil.Prettify(s)
|
||||
}
|
||||
|
||||
// GoString returns the string representation
|
||||
func (s EnableVpcClassicLinkDnsSupportInput) GoString() string {
|
||||
return s.String()
|
||||
}
|
||||
|
||||
type EnableVpcClassicLinkDnsSupportOutput struct {
|
||||
_ struct{} `type:"structure"`
|
||||
|
||||
// Returns true if the request succeeds; otherwise, it returns an error.
|
||||
Return *bool `locationName:"return" type:"boolean"`
|
||||
}
|
||||
|
||||
// String returns the string representation
|
||||
func (s EnableVpcClassicLinkDnsSupportOutput) String() string {
|
||||
return awsutil.Prettify(s)
|
||||
}
|
||||
|
||||
// GoString returns the string representation
|
||||
func (s EnableVpcClassicLinkDnsSupportOutput) GoString() string {
|
||||
return s.String()
|
||||
}
|
||||
|
||||
type EnableVpcClassicLinkInput struct {
|
||||
_ struct{} `type:"structure"`
|
||||
|
||||
@ -16018,7 +16254,8 @@ type GetConsoleOutputOutput struct {
|
||||
// The ID of the instance.
|
||||
InstanceId *string `locationName:"instanceId" type:"string"`
|
||||
|
||||
// The console output, Base64 encoded.
|
||||
// The console output, Base64 encoded. If using a command line tool, the tools
|
||||
// decode the output for you.
|
||||
Output *string `locationName:"output" type:"string"`
|
||||
|
||||
// The time the output was last updated.
|
||||
@ -21060,7 +21297,12 @@ type RunInstancesInput struct {
|
||||
// [EC2-VPC] The ID of the subnet to launch the instance into.
|
||||
SubnetId *string `type:"string"`
|
||||
|
||||
// The Base64-encoded MIME user data for the instances.
|
||||
// Data to configure the instance, or a script to run during instance launch.
|
||||
// For more information, see Running Commands on Your Linux Instance at Launch
|
||||
// (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html) (Linux)
|
||||
// and Adding User Data (http://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ec2-instance-metadata.html#instancedata-add-user-data)
|
||||
// (Windows). For API calls, the text must be base64-encoded. Command line tools
|
||||
// perform encoding for you.
|
||||
UserData *string `type:"string"`
|
||||
}
|
||||
|
||||
@ -21826,7 +22068,8 @@ type StateReason struct {
|
||||
// Client.UserInitiatedShutdown: The instance was shut down using the Amazon
|
||||
// EC2 API.
|
||||
//
|
||||
// Client.VolumeLimitExceeded: The volume limit was exceeded.
|
||||
// Client.VolumeLimitExceeded: The limit on the number of EBS volumes or total
|
||||
// storage was exceeded. Decrease usage or request an increase in your limits.
|
||||
//
|
||||
// Client.InvalidSnapshot.NotFound: The specified snapshot was not found.
|
||||
Message *string `locationName:"message" type:"string"`
|
||||
@ -22811,7 +23054,8 @@ func (s VpnConnectionOptionsSpecification) GoString() string {
|
||||
type VpnGateway struct {
|
||||
_ struct{} `type:"structure"`
|
||||
|
||||
// The Availability Zone where the virtual private gateway was created.
|
||||
// The Availability Zone where the virtual private gateway was created, if applicable.
|
||||
// This field may be empty or not returned.
|
||||
AvailabilityZone *string `locationName:"availabilityZone" type:"string"`
|
||||
|
||||
// The current state of the virtual private gateway.
|
||||
@ -23242,6 +23486,8 @@ const (
|
||||
// @enum InstanceType
|
||||
InstanceTypeM410xlarge = "m4.10xlarge"
|
||||
// @enum InstanceType
|
||||
InstanceTypeT2Nano = "t2.nano"
|
||||
// @enum InstanceType
|
||||
InstanceTypeT2Micro = "t2.micro"
|
||||
// @enum InstanceType
|
||||
InstanceTypeT2Small = "t2.small"
|
||||
|
14
vendor/github.com/aws/aws-sdk-go/service/ecr/service.go
generated
vendored
14
vendor/github.com/aws/aws-sdk-go/service/ecr/service.go
generated
vendored
@ -11,14 +11,12 @@ import (
|
||||
"github.com/aws/aws-sdk-go/private/signer/v4"
|
||||
)
|
||||
|
||||
// The Amazon EC2 Container Registry makes it easier to manage public and private
|
||||
// Docker images for AWS or on-premises environments. Amazon ECR supports resource-level
|
||||
// permissions to control who can create, update, use, or delete images. Users
|
||||
// and groups can be created individually in AWS Identity and Access Management
|
||||
// (IAM) or federated with enterprise directories such as Microsoft Active Directory.
|
||||
// Images are stored on highly durable AWS infrastructure and include built-in
|
||||
// caching so that starting hundreds of containers is as fast as starting a
|
||||
// single container.
|
||||
// Amazon EC2 Container Registry (Amazon ECR) is a managed AWS Docker registry
|
||||
// service. Customers can use the familiar Docker CLI to push, pull, and manage
|
||||
// images. Amazon ECR provides a secure, scalable, and reliable registry. Amazon
|
||||
// ECR supports private Docker repositories with resource-based permissions
|
||||
// using AWS IAM so that specific users or Amazon EC2 instances can access repositories
|
||||
// and images. Developers can use the Docker CLI to author and manage images.
|
||||
//The service client's operations are safe to be used concurrently.
|
||||
// It is not safe to mutate any of the client's properties though.
|
||||
type ECR struct {
|
||||
|
4
vendor/github.com/aws/aws-sdk-go/vendor/github.com/go-ini/ini/.gitignore
generated
vendored
Normal file
4
vendor/github.com/aws/aws-sdk-go/vendor/github.com/go-ini/ini/.gitignore
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
testdata/conf_out.ini
|
||||
ini.sublime-project
|
||||
ini.sublime-workspace
|
||||
testdata/conf_reflect.ini
|
191
vendor/github.com/aws/aws-sdk-go/vendor/github.com/go-ini/ini/LICENSE
generated
vendored
Normal file
191
vendor/github.com/aws/aws-sdk-go/vendor/github.com/go-ini/ini/LICENSE
generated
vendored
Normal file
@ -0,0 +1,191 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, and
|
||||
distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by the copyright
|
||||
owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all other entities
|
||||
that control, are controlled by, or are under common control with that entity.
|
||||
For the purposes of this definition, "control" means (i) the power, direct or
|
||||
indirect, to cause the direction or management of such entity, whether by
|
||||
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity exercising
|
||||
permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications, including
|
||||
but not limited to software source code, documentation source, and configuration
|
||||
files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical transformation or
|
||||
translation of a Source form, including but not limited to compiled object code,
|
||||
generated documentation, and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or Object form, made
|
||||
available under the License, as indicated by a copyright notice that is included
|
||||
in or attached to the work (an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object form, that
|
||||
is based on (or derived from) the Work and for which the editorial revisions,
|
||||
annotations, elaborations, or other modifications represent, as a whole, an
|
||||
original work of authorship. For the purposes of this License, Derivative Works
|
||||
shall not include works that remain separable from, or merely link (or bind by
|
||||
name) to the interfaces of, the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including the original version
|
||||
of the Work and any modifications or additions to that Work or Derivative Works
|
||||
thereof, that is intentionally submitted to Licensor for inclusion in the Work
|
||||
by the copyright owner or by an individual or Legal Entity authorized to submit
|
||||
on behalf of the copyright owner. For the purposes of this definition,
|
||||
"submitted" means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems, and
|
||||
issue tracking systems that are managed by, or on behalf of, the Licensor for
|
||||
the purpose of discussing and improving the Work, but excluding communication
|
||||
that is conspicuously marked or otherwise designated in writing by the copyright
|
||||
owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
|
||||
of whom a Contribution has been received by Licensor and subsequently
|
||||
incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License.
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby
|
||||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||
irrevocable copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the Work and such
|
||||
Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License.
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby
|
||||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||
irrevocable (except as stated in this section) patent license to make, have
|
||||
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
|
||||
such license applies only to those patent claims licensable by such Contributor
|
||||
that are necessarily infringed by their Contribution(s) alone or by combination
|
||||
of their Contribution(s) with the Work to which such Contribution(s) was
|
||||
submitted. If You institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
|
||||
Contribution incorporated within the Work constitutes direct or contributory
|
||||
patent infringement, then any patent licenses granted to You under this License
|
||||
for that Work shall terminate as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution.
|
||||
|
||||
You may reproduce and distribute copies of the Work or Derivative Works thereof
|
||||
in any medium, with or without modifications, and in Source or Object form,
|
||||
provided that You meet the following conditions:
|
||||
|
||||
You must give any other recipients of the Work or Derivative Works a copy of
|
||||
this License; and
|
||||
You must cause any modified files to carry prominent notices stating that You
|
||||
changed the files; and
|
||||
You must retain, in the Source form of any Derivative Works that You distribute,
|
||||
all copyright, patent, trademark, and attribution notices from the Source form
|
||||
of the Work, excluding those notices that do not pertain to any part of the
|
||||
Derivative Works; and
|
||||
If the Work includes a "NOTICE" text file as part of its distribution, then any
|
||||
Derivative Works that You distribute must include a readable copy of the
|
||||
attribution notices contained within such NOTICE file, excluding those notices
|
||||
that do not pertain to any part of the Derivative Works, in at least one of the
|
||||
following places: within a NOTICE text file distributed as part of the
|
||||
Derivative Works; within the Source form or documentation, if provided along
|
||||
with the Derivative Works; or, within a display generated by the Derivative
|
||||
Works, if and wherever such third-party notices normally appear. The contents of
|
||||
the NOTICE file are for informational purposes only and do not modify the
|
||||
License. You may add Your own attribution notices within Derivative Works that
|
||||
You distribute, alongside or as an addendum to the NOTICE text from the Work,
|
||||
provided that such additional attribution notices cannot be construed as
|
||||
modifying the License.
|
||||
You may add Your own copyright statement to Your modifications and may provide
|
||||
additional or different license terms and conditions for use, reproduction, or
|
||||
distribution of Your modifications, or for any such Derivative Works as a whole,
|
||||
provided Your use, reproduction, and distribution of the Work otherwise complies
|
||||
with the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions.
|
||||
|
||||
Unless You explicitly state otherwise, any Contribution intentionally submitted
|
||||
for inclusion in the Work by You to the Licensor shall be under the terms and
|
||||
conditions of this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify the terms of
|
||||
any separate license agreement you may have executed with Licensor regarding
|
||||
such Contributions.
|
||||
|
||||
6. Trademarks.
|
||||
|
||||
This License does not grant permission to use the trade names, trademarks,
|
||||
service marks, or product names of the Licensor, except as required for
|
||||
reasonable and customary use in describing the origin of the Work and
|
||||
reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, Licensor provides the
|
||||
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
|
||||
including, without limitation, any warranties or conditions of TITLE,
|
||||
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
|
||||
solely responsible for determining the appropriateness of using or
|
||||
redistributing the Work and assume any risks associated with Your exercise of
|
||||
permissions under this License.
|
||||
|
||||
8. Limitation of Liability.
|
||||
|
||||
In no event and under no legal theory, whether in tort (including negligence),
|
||||
contract, or otherwise, unless required by applicable law (such as deliberate
|
||||
and grossly negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special, incidental,
|
||||
or consequential damages of any character arising as a result of this License or
|
||||
out of the use or inability to use the Work (including but not limited to
|
||||
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
|
||||
any and all other commercial damages or losses), even if such Contributor has
|
||||
been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability.
|
||||
|
||||
While redistributing the Work or Derivative Works thereof, You may choose to
|
||||
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
|
||||
other liability obligations and/or rights consistent with this License. However,
|
||||
in accepting such obligations, You may act only on Your own behalf and on Your
|
||||
sole responsibility, not on behalf of any other Contributor, and only if You
|
||||
agree to indemnify, defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason of your
|
||||
accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work
|
||||
|
||||
To apply the Apache License to your work, attach the following boilerplate
|
||||
notice, with the fields enclosed by brackets "[]" replaced with your own
|
||||
identifying information. (Don't include the brackets!) The text should be
|
||||
enclosed in the appropriate comment syntax for the file format. We also
|
||||
recommend that a file or class name and description of purpose be included on
|
||||
the same "printed page" as the copyright notice for easier identification within
|
||||
third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed 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.
|
560
vendor/github.com/aws/aws-sdk-go/vendor/github.com/go-ini/ini/README.md
generated
vendored
Normal file
560
vendor/github.com/aws/aws-sdk-go/vendor/github.com/go-ini/ini/README.md
generated
vendored
Normal file
@ -0,0 +1,560 @@
|
||||
ini [](https://drone.io/github.com/go-ini/ini/latest) [](http://gocover.io/github.com/go-ini/ini)
|
||||
===
|
||||
|
||||

|
||||
|
||||
Package ini provides INI file read and write functionality in Go.
|
||||
|
||||
[简体中文](README_ZH.md)
|
||||
|
||||
## Feature
|
||||
|
||||
- Load multiple data sources(`[]byte` or file) with overwrites.
|
||||
- Read with recursion values.
|
||||
- Read with parent-child sections.
|
||||
- Read with auto-increment key names.
|
||||
- Read with multiple-line values.
|
||||
- Read with tons of helper methods.
|
||||
- Read and convert values to Go types.
|
||||
- Read and **WRITE** comments of sections and keys.
|
||||
- Manipulate sections, keys and comments with ease.
|
||||
- Keep sections and keys in order as you parse and save.
|
||||
|
||||
## Installation
|
||||
|
||||
go get gopkg.in/ini.v1
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Loading from data sources
|
||||
|
||||
A **Data Source** is either raw data in type `[]byte` or a file name with type `string` and you can load **as many as** data sources you want. Passing other types will simply return an error.
|
||||
|
||||
```go
|
||||
cfg, err := ini.Load([]byte("raw data"), "filename")
|
||||
```
|
||||
|
||||
Or start with an empty object:
|
||||
|
||||
```go
|
||||
cfg := ini.Empty()
|
||||
```
|
||||
|
||||
When you cannot decide how many data sources to load at the beginning, you still able to **Append()** them later.
|
||||
|
||||
```go
|
||||
err := cfg.Append("other file", []byte("other raw data"))
|
||||
```
|
||||
|
||||
### Working with sections
|
||||
|
||||
To get a section, you would need to:
|
||||
|
||||
```go
|
||||
section, err := cfg.GetSection("section name")
|
||||
```
|
||||
|
||||
For a shortcut for default section, just give an empty string as name:
|
||||
|
||||
```go
|
||||
section, err := cfg.GetSection("")
|
||||
```
|
||||
|
||||
When you're pretty sure the section exists, following code could make your life easier:
|
||||
|
||||
```go
|
||||
section := cfg.Section("")
|
||||
```
|
||||
|
||||
What happens when the section somehow does not exist? Don't panic, it automatically creates and returns a new section to you.
|
||||
|
||||
To create a new section:
|
||||
|
||||
```go
|
||||
err := cfg.NewSection("new section")
|
||||
```
|
||||
|
||||
To get a list of sections or section names:
|
||||
|
||||
```go
|
||||
sections := cfg.Sections()
|
||||
names := cfg.SectionStrings()
|
||||
```
|
||||
|
||||
### Working with keys
|
||||
|
||||
To get a key under a section:
|
||||
|
||||
```go
|
||||
key, err := cfg.Section("").GetKey("key name")
|
||||
```
|
||||
|
||||
Same rule applies to key operations:
|
||||
|
||||
```go
|
||||
key := cfg.Section("").Key("key name")
|
||||
```
|
||||
|
||||
To create a new key:
|
||||
|
||||
```go
|
||||
err := cfg.Section("").NewKey("name", "value")
|
||||
```
|
||||
|
||||
To get a list of keys or key names:
|
||||
|
||||
```go
|
||||
keys := cfg.Section("").Keys()
|
||||
names := cfg.Section("").KeyStrings()
|
||||
```
|
||||
|
||||
To get a clone hash of keys and corresponding values:
|
||||
|
||||
```go
|
||||
hash := cfg.GetSection("").KeysHash()
|
||||
```
|
||||
|
||||
### Working with values
|
||||
|
||||
To get a string value:
|
||||
|
||||
```go
|
||||
val := cfg.Section("").Key("key name").String()
|
||||
```
|
||||
|
||||
To validate key value on the fly:
|
||||
|
||||
```go
|
||||
val := cfg.Section("").Key("key name").Validate(func(in string) string {
|
||||
if len(in) == 0 {
|
||||
return "default"
|
||||
}
|
||||
return in
|
||||
})
|
||||
```
|
||||
|
||||
To get value with types:
|
||||
|
||||
```go
|
||||
// For boolean values:
|
||||
// true when value is: 1, t, T, TRUE, true, True, YES, yes, Yes, ON, on, On
|
||||
// false when value is: 0, f, F, FALSE, false, False, NO, no, No, OFF, off, Off
|
||||
v, err = cfg.Section("").Key("BOOL").Bool()
|
||||
v, err = cfg.Section("").Key("FLOAT64").Float64()
|
||||
v, err = cfg.Section("").Key("INT").Int()
|
||||
v, err = cfg.Section("").Key("INT64").Int64()
|
||||
v, err = cfg.Section("").Key("UINT").Uint()
|
||||
v, err = cfg.Section("").Key("UINT64").Uint64()
|
||||
v, err = cfg.Section("").Key("TIME").TimeFormat(time.RFC3339)
|
||||
v, err = cfg.Section("").Key("TIME").Time() // RFC3339
|
||||
|
||||
v = cfg.Section("").Key("BOOL").MustBool()
|
||||
v = cfg.Section("").Key("FLOAT64").MustFloat64()
|
||||
v = cfg.Section("").Key("INT").MustInt()
|
||||
v = cfg.Section("").Key("INT64").MustInt64()
|
||||
v = cfg.Section("").Key("UINT").MustUint()
|
||||
v = cfg.Section("").Key("UINT64").MustUint64()
|
||||
v = cfg.Section("").Key("TIME").MustTimeFormat(time.RFC3339)
|
||||
v = cfg.Section("").Key("TIME").MustTime() // RFC3339
|
||||
|
||||
// Methods start with Must also accept one argument for default value
|
||||
// when key not found or fail to parse value to given type.
|
||||
// Except method MustString, which you have to pass a default value.
|
||||
|
||||
v = cfg.Section("").Key("String").MustString("default")
|
||||
v = cfg.Section("").Key("BOOL").MustBool(true)
|
||||
v = cfg.Section("").Key("FLOAT64").MustFloat64(1.25)
|
||||
v = cfg.Section("").Key("INT").MustInt(10)
|
||||
v = cfg.Section("").Key("INT64").MustInt64(99)
|
||||
v = cfg.Section("").Key("UINT").MustUint(3)
|
||||
v = cfg.Section("").Key("UINT64").MustUint64(6)
|
||||
v = cfg.Section("").Key("TIME").MustTimeFormat(time.RFC3339, time.Now())
|
||||
v = cfg.Section("").Key("TIME").MustTime(time.Now()) // RFC3339
|
||||
```
|
||||
|
||||
What if my value is three-line long?
|
||||
|
||||
```ini
|
||||
[advance]
|
||||
ADDRESS = """404 road,
|
||||
NotFound, State, 5000
|
||||
Earth"""
|
||||
```
|
||||
|
||||
Not a problem!
|
||||
|
||||
```go
|
||||
cfg.Section("advance").Key("ADDRESS").String()
|
||||
|
||||
/* --- start ---
|
||||
404 road,
|
||||
NotFound, State, 5000
|
||||
Earth
|
||||
------ end --- */
|
||||
```
|
||||
|
||||
That's cool, how about continuation lines?
|
||||
|
||||
```ini
|
||||
[advance]
|
||||
two_lines = how about \
|
||||
continuation lines?
|
||||
lots_of_lines = 1 \
|
||||
2 \
|
||||
3 \
|
||||
4
|
||||
```
|
||||
|
||||
Piece of cake!
|
||||
|
||||
```go
|
||||
cfg.Section("advance").Key("two_lines").String() // how about continuation lines?
|
||||
cfg.Section("advance").Key("lots_of_lines").String() // 1 2 3 4
|
||||
```
|
||||
|
||||
Note that single quotes around values will be stripped:
|
||||
|
||||
```ini
|
||||
foo = "some value" // foo: some value
|
||||
bar = 'some value' // bar: some value
|
||||
```
|
||||
|
||||
That's all? Hmm, no.
|
||||
|
||||
#### Helper methods of working with values
|
||||
|
||||
To get value with given candidates:
|
||||
|
||||
```go
|
||||
v = cfg.Section("").Key("STRING").In("default", []string{"str", "arr", "types"})
|
||||
v = cfg.Section("").Key("FLOAT64").InFloat64(1.1, []float64{1.25, 2.5, 3.75})
|
||||
v = cfg.Section("").Key("INT").InInt(5, []int{10, 20, 30})
|
||||
v = cfg.Section("").Key("INT64").InInt64(10, []int64{10, 20, 30})
|
||||
v = cfg.Section("").Key("UINT").InUint(4, []int{3, 6, 9})
|
||||
v = cfg.Section("").Key("UINT64").InUint64(8, []int64{3, 6, 9})
|
||||
v = cfg.Section("").Key("TIME").InTimeFormat(time.RFC3339, time.Now(), []time.Time{time1, time2, time3})
|
||||
v = cfg.Section("").Key("TIME").InTime(time.Now(), []time.Time{time1, time2, time3}) // RFC3339
|
||||
```
|
||||
|
||||
Default value will be presented if value of key is not in candidates you given, and default value does not need be one of candidates.
|
||||
|
||||
To validate value in a given range:
|
||||
|
||||
```go
|
||||
vals = cfg.Section("").Key("FLOAT64").RangeFloat64(0.0, 1.1, 2.2)
|
||||
vals = cfg.Section("").Key("INT").RangeInt(0, 10, 20)
|
||||
vals = cfg.Section("").Key("INT64").RangeInt64(0, 10, 20)
|
||||
vals = cfg.Section("").Key("UINT").RangeUint(0, 3, 9)
|
||||
vals = cfg.Section("").Key("UINT64").RangeUint64(0, 3, 9)
|
||||
vals = cfg.Section("").Key("TIME").RangeTimeFormat(time.RFC3339, time.Now(), minTime, maxTime)
|
||||
vals = cfg.Section("").Key("TIME").RangeTime(time.Now(), minTime, maxTime) // RFC3339
|
||||
```
|
||||
|
||||
To auto-split value into slice:
|
||||
|
||||
```go
|
||||
vals = cfg.Section("").Key("STRINGS").Strings(",")
|
||||
vals = cfg.Section("").Key("FLOAT64S").Float64s(",")
|
||||
vals = cfg.Section("").Key("INTS").Ints(",")
|
||||
vals = cfg.Section("").Key("INT64S").Int64s(",")
|
||||
vals = cfg.Section("").Key("UINTS").Uints(",")
|
||||
vals = cfg.Section("").Key("UINT64S").Uint64s(",")
|
||||
vals = cfg.Section("").Key("TIMES").Times(",")
|
||||
```
|
||||
|
||||
### Save your configuration
|
||||
|
||||
Finally, it's time to save your configuration to somewhere.
|
||||
|
||||
A typical way to save configuration is writing it to a file:
|
||||
|
||||
```go
|
||||
// ...
|
||||
err = cfg.SaveTo("my.ini")
|
||||
err = cfg.SaveToIndent("my.ini", "\t")
|
||||
```
|
||||
|
||||
Another way to save is writing to a `io.Writer` interface:
|
||||
|
||||
```go
|
||||
// ...
|
||||
cfg.WriteTo(writer)
|
||||
cfg.WriteToIndent(writer, "\t")
|
||||
```
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Recursive Values
|
||||
|
||||
For all value of keys, there is a special syntax `%(<name>)s`, where `<name>` is the key name in same section or default section, and `%(<name>)s` will be replaced by corresponding value(empty string if key not found). You can use this syntax at most 99 level of recursions.
|
||||
|
||||
```ini
|
||||
NAME = ini
|
||||
|
||||
[author]
|
||||
NAME = Unknwon
|
||||
GITHUB = https://github.com/%(NAME)s
|
||||
|
||||
[package]
|
||||
FULL_NAME = github.com/go-ini/%(NAME)s
|
||||
```
|
||||
|
||||
```go
|
||||
cfg.Section("author").Key("GITHUB").String() // https://github.com/Unknwon
|
||||
cfg.Section("package").Key("FULL_NAME").String() // github.com/go-ini/ini
|
||||
```
|
||||
|
||||
### Parent-child Sections
|
||||
|
||||
You can use `.` in section name to indicate parent-child relationship between two or more sections. If the key not found in the child section, library will try again on its parent section until there is no parent section.
|
||||
|
||||
```ini
|
||||
NAME = ini
|
||||
VERSION = v1
|
||||
IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s
|
||||
|
||||
[package]
|
||||
CLONE_URL = https://%(IMPORT_PATH)s
|
||||
|
||||
[package.sub]
|
||||
```
|
||||
|
||||
```go
|
||||
cfg.Section("package.sub").Key("CLONE_URL").String() // https://gopkg.in/ini.v1
|
||||
```
|
||||
|
||||
### Auto-increment Key Names
|
||||
|
||||
If key name is `-` in data source, then it would be seen as special syntax for auto-increment key name start from 1, and every section is independent on counter.
|
||||
|
||||
```ini
|
||||
[features]
|
||||
-: Support read/write comments of keys and sections
|
||||
-: Support auto-increment of key names
|
||||
-: Support load multiple files to overwrite key values
|
||||
```
|
||||
|
||||
```go
|
||||
cfg.Section("features").KeyStrings() // []{"#1", "#2", "#3"}
|
||||
```
|
||||
|
||||
### Map To Struct
|
||||
|
||||
Want more objective way to play with INI? Cool.
|
||||
|
||||
```ini
|
||||
Name = Unknwon
|
||||
age = 21
|
||||
Male = true
|
||||
Born = 1993-01-01T20:17:05Z
|
||||
|
||||
[Note]
|
||||
Content = Hi is a good man!
|
||||
Cities = HangZhou, Boston
|
||||
```
|
||||
|
||||
```go
|
||||
type Note struct {
|
||||
Content string
|
||||
Cities []string
|
||||
}
|
||||
|
||||
type Person struct {
|
||||
Name string
|
||||
Age int `ini:"age"`
|
||||
Male bool
|
||||
Born time.Time
|
||||
Note
|
||||
Created time.Time `ini:"-"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
cfg, err := ini.Load("path/to/ini")
|
||||
// ...
|
||||
p := new(Person)
|
||||
err = cfg.MapTo(p)
|
||||
// ...
|
||||
|
||||
// Things can be simpler.
|
||||
err = ini.MapTo(p, "path/to/ini")
|
||||
// ...
|
||||
|
||||
// Just map a section? Fine.
|
||||
n := new(Note)
|
||||
err = cfg.Section("Note").MapTo(n)
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Can I have default value for field? Absolutely.
|
||||
|
||||
Assign it before you map to struct. It will keep the value as it is if the key is not presented or got wrong type.
|
||||
|
||||
```go
|
||||
// ...
|
||||
p := &Person{
|
||||
Name: "Joe",
|
||||
}
|
||||
// ...
|
||||
```
|
||||
|
||||
It's really cool, but what's the point if you can't give me my file back from struct?
|
||||
|
||||
### Reflect From Struct
|
||||
|
||||
Why not?
|
||||
|
||||
```go
|
||||
type Embeded struct {
|
||||
Dates []time.Time `delim:"|"`
|
||||
Places []string
|
||||
None []int
|
||||
}
|
||||
|
||||
type Author struct {
|
||||
Name string `ini:"NAME"`
|
||||
Male bool
|
||||
Age int
|
||||
GPA float64
|
||||
NeverMind string `ini:"-"`
|
||||
*Embeded
|
||||
}
|
||||
|
||||
func main() {
|
||||
a := &Author{"Unknwon", true, 21, 2.8, "",
|
||||
&Embeded{
|
||||
[]time.Time{time.Now(), time.Now()},
|
||||
[]string{"HangZhou", "Boston"},
|
||||
[]int{},
|
||||
}}
|
||||
cfg := ini.Empty()
|
||||
err = ini.ReflectFrom(cfg, a)
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
So, what do I get?
|
||||
|
||||
```ini
|
||||
NAME = Unknwon
|
||||
Male = true
|
||||
Age = 21
|
||||
GPA = 2.8
|
||||
|
||||
[Embeded]
|
||||
Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00
|
||||
Places = HangZhou,Boston
|
||||
None =
|
||||
```
|
||||
|
||||
#### Name Mapper
|
||||
|
||||
To save your time and make your code cleaner, this library supports [`NameMapper`](https://gowalker.org/gopkg.in/ini.v1#NameMapper) between struct field and actual section and key name.
|
||||
|
||||
There are 2 built-in name mappers:
|
||||
|
||||
- `AllCapsUnderscore`: it converts to format `ALL_CAPS_UNDERSCORE` then match section or key.
|
||||
- `TitleUnderscore`: it converts to format `title_underscore` then match section or key.
|
||||
|
||||
To use them:
|
||||
|
||||
```go
|
||||
type Info struct {
|
||||
PackageName string
|
||||
}
|
||||
|
||||
func main() {
|
||||
err = ini.MapToWithMapper(&Info{}, ini.TitleUnderscore, []byte("packag_name=ini"))
|
||||
// ...
|
||||
|
||||
cfg, err := ini.Load([]byte("PACKAGE_NAME=ini"))
|
||||
// ...
|
||||
info := new(Info)
|
||||
cfg.NameMapper = ini.AllCapsUnderscore
|
||||
err = cfg.MapTo(info)
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Same rules of name mapper apply to `ini.ReflectFromWithMapper` function.
|
||||
|
||||
#### Other Notes On Map/Reflect
|
||||
|
||||
Any embedded struct is treated as a section by default, and there is no automatic parent-child relations in map/reflect feature:
|
||||
|
||||
```go
|
||||
type Child struct {
|
||||
Age string
|
||||
}
|
||||
|
||||
type Parent struct {
|
||||
Name string
|
||||
Child
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
City string
|
||||
Parent
|
||||
}
|
||||
```
|
||||
|
||||
Example configuration:
|
||||
|
||||
```ini
|
||||
City = Boston
|
||||
|
||||
[Parent]
|
||||
Name = Unknwon
|
||||
|
||||
[Child]
|
||||
Age = 21
|
||||
```
|
||||
|
||||
What if, yes, I'm paranoid, I want embedded struct to be in the same section. Well, all roads lead to Rome.
|
||||
|
||||
```go
|
||||
type Child struct {
|
||||
Age string
|
||||
}
|
||||
|
||||
type Parent struct {
|
||||
Name string
|
||||
Child `ini:"Parent"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
City string
|
||||
Parent
|
||||
}
|
||||
```
|
||||
|
||||
Example configuration:
|
||||
|
||||
```ini
|
||||
City = Boston
|
||||
|
||||
[Parent]
|
||||
Name = Unknwon
|
||||
Age = 21
|
||||
```
|
||||
|
||||
## Getting Help
|
||||
|
||||
- [API Documentation](https://gowalker.org/gopkg.in/ini.v1)
|
||||
- [File An Issue](https://github.com/go-ini/ini/issues/new)
|
||||
|
||||
## FAQs
|
||||
|
||||
### What does `BlockMode` field do?
|
||||
|
||||
By default, library lets you read and write values so we need a locker to make sure your data is safe. But in cases that you are very sure about only reading data through the library, you can set `cfg.BlockMode = false` to speed up read operations about **50-70%** faster.
|
||||
|
||||
### Why another INI library?
|
||||
|
||||
Many people are using my another INI library [goconfig](https://github.com/Unknwon/goconfig), so the reason for this one is I would like to make more Go style code. Also when you set `cfg.BlockMode = false`, this one is about **10-30%** faster.
|
||||
|
||||
To make those changes I have to confirm API broken, so it's safer to keep it in another place and start using `gopkg.in` to version my package at this time.(PS: shorter import path)
|
||||
|
||||
## License
|
||||
|
||||
This project is under Apache v2 License. See the [LICENSE](LICENSE) file for the full license text.
|
547
vendor/github.com/aws/aws-sdk-go/vendor/github.com/go-ini/ini/README_ZH.md
generated
vendored
Normal file
547
vendor/github.com/aws/aws-sdk-go/vendor/github.com/go-ini/ini/README_ZH.md
generated
vendored
Normal file
@ -0,0 +1,547 @@
|
||||
本包提供了 Go 语言中读写 INI 文件的功能。
|
||||
|
||||
## 功能特性
|
||||
|
||||
- 支持覆盖加载多个数据源(`[]byte` 或文件)
|
||||
- 支持递归读取键值
|
||||
- 支持读取父子分区
|
||||
- 支持读取自增键名
|
||||
- 支持读取多行的键值
|
||||
- 支持大量辅助方法
|
||||
- 支持在读取时直接转换为 Go 语言类型
|
||||
- 支持读取和 **写入** 分区和键的注释
|
||||
- 轻松操作分区、键值和注释
|
||||
- 在保存文件时分区和键值会保持原有的顺序
|
||||
|
||||
## 下载安装
|
||||
|
||||
go get gopkg.in/ini.v1
|
||||
|
||||
## 开始使用
|
||||
|
||||
### 从数据源加载
|
||||
|
||||
一个 **数据源** 可以是 `[]byte` 类型的原始数据,或 `string` 类型的文件路径。您可以加载 **任意多个** 数据源。如果您传递其它类型的数据源,则会直接返回错误。
|
||||
|
||||
```go
|
||||
cfg, err := ini.Load([]byte("raw data"), "filename")
|
||||
```
|
||||
|
||||
或者从一个空白的文件开始:
|
||||
|
||||
```go
|
||||
cfg := ini.Empty()
|
||||
```
|
||||
|
||||
当您在一开始无法决定需要加载哪些数据源时,仍可以使用 **Append()** 在需要的时候加载它们。
|
||||
|
||||
```go
|
||||
err := cfg.Append("other file", []byte("other raw data"))
|
||||
```
|
||||
|
||||
### 操作分区(Section)
|
||||
|
||||
获取指定分区:
|
||||
|
||||
```go
|
||||
section, err := cfg.GetSection("section name")
|
||||
```
|
||||
|
||||
如果您想要获取默认分区,则可以用空字符串代替分区名:
|
||||
|
||||
```go
|
||||
section, err := cfg.GetSection("")
|
||||
```
|
||||
|
||||
当您非常确定某个分区是存在的,可以使用以下简便方法:
|
||||
|
||||
```go
|
||||
section := cfg.Section("")
|
||||
```
|
||||
|
||||
如果不小心判断错了,要获取的分区其实是不存在的,那会发生什么呢?没事的,它会自动创建并返回一个对应的分区对象给您。
|
||||
|
||||
创建一个分区:
|
||||
|
||||
```go
|
||||
err := cfg.NewSection("new section")
|
||||
```
|
||||
|
||||
获取所有分区对象或名称:
|
||||
|
||||
```go
|
||||
sections := cfg.Sections()
|
||||
names := cfg.SectionStrings()
|
||||
```
|
||||
|
||||
### 操作键(Key)
|
||||
|
||||
获取某个分区下的键:
|
||||
|
||||
```go
|
||||
key, err := cfg.Section("").GetKey("key name")
|
||||
```
|
||||
|
||||
和分区一样,您也可以直接获取键而忽略错误处理:
|
||||
|
||||
```go
|
||||
key := cfg.Section("").Key("key name")
|
||||
```
|
||||
|
||||
创建一个新的键:
|
||||
|
||||
```go
|
||||
err := cfg.Section("").NewKey("name", "value")
|
||||
```
|
||||
|
||||
获取分区下的所有键或键名:
|
||||
|
||||
```go
|
||||
keys := cfg.Section("").Keys()
|
||||
names := cfg.Section("").KeyStrings()
|
||||
```
|
||||
|
||||
获取分区下的所有键值对的克隆:
|
||||
|
||||
```go
|
||||
hash := cfg.GetSection("").KeysHash()
|
||||
```
|
||||
|
||||
### 操作键值(Value)
|
||||
|
||||
获取一个类型为字符串(string)的值:
|
||||
|
||||
```go
|
||||
val := cfg.Section("").Key("key name").String()
|
||||
```
|
||||
|
||||
获取值的同时通过自定义函数进行处理验证:
|
||||
|
||||
```go
|
||||
val := cfg.Section("").Key("key name").Validate(func(in string) string {
|
||||
if len(in) == 0 {
|
||||
return "default"
|
||||
}
|
||||
return in
|
||||
})
|
||||
```
|
||||
|
||||
获取其它类型的值:
|
||||
|
||||
```go
|
||||
// 布尔值的规则:
|
||||
// true 当值为:1, t, T, TRUE, true, True, YES, yes, Yes, ON, on, On
|
||||
// false 当值为:0, f, F, FALSE, false, False, NO, no, No, OFF, off, Off
|
||||
v, err = cfg.Section("").Key("BOOL").Bool()
|
||||
v, err = cfg.Section("").Key("FLOAT64").Float64()
|
||||
v, err = cfg.Section("").Key("INT").Int()
|
||||
v, err = cfg.Section("").Key("INT64").Int64()
|
||||
v, err = cfg.Section("").Key("UINT").Uint()
|
||||
v, err = cfg.Section("").Key("UINT64").Uint64()
|
||||
v, err = cfg.Section("").Key("TIME").TimeFormat(time.RFC3339)
|
||||
v, err = cfg.Section("").Key("TIME").Time() // RFC3339
|
||||
|
||||
v = cfg.Section("").Key("BOOL").MustBool()
|
||||
v = cfg.Section("").Key("FLOAT64").MustFloat64()
|
||||
v = cfg.Section("").Key("INT").MustInt()
|
||||
v = cfg.Section("").Key("INT64").MustInt64()
|
||||
v = cfg.Section("").Key("UINT").MustUint()
|
||||
v = cfg.Section("").Key("UINT64").MustUint64()
|
||||
v = cfg.Section("").Key("TIME").MustTimeFormat(time.RFC3339)
|
||||
v = cfg.Section("").Key("TIME").MustTime() // RFC3339
|
||||
|
||||
// 由 Must 开头的方法名允许接收一个相同类型的参数来作为默认值,
|
||||
// 当键不存在或者转换失败时,则会直接返回该默认值。
|
||||
// 但是,MustString 方法必须传递一个默认值。
|
||||
|
||||
v = cfg.Seciont("").Key("String").MustString("default")
|
||||
v = cfg.Section("").Key("BOOL").MustBool(true)
|
||||
v = cfg.Section("").Key("FLOAT64").MustFloat64(1.25)
|
||||
v = cfg.Section("").Key("INT").MustInt(10)
|
||||
v = cfg.Section("").Key("INT64").MustInt64(99)
|
||||
v = cfg.Section("").Key("UINT").MustUint(3)
|
||||
v = cfg.Section("").Key("UINT64").MustUint64(6)
|
||||
v = cfg.Section("").Key("TIME").MustTimeFormat(time.RFC3339, time.Now())
|
||||
v = cfg.Section("").Key("TIME").MustTime(time.Now()) // RFC3339
|
||||
```
|
||||
|
||||
如果我的值有好多行怎么办?
|
||||
|
||||
```ini
|
||||
[advance]
|
||||
ADDRESS = """404 road,
|
||||
NotFound, State, 5000
|
||||
Earth"""
|
||||
```
|
||||
|
||||
嗯哼?小 case!
|
||||
|
||||
```go
|
||||
cfg.Section("advance").Key("ADDRESS").String()
|
||||
|
||||
/* --- start ---
|
||||
404 road,
|
||||
NotFound, State, 5000
|
||||
Earth
|
||||
------ end --- */
|
||||
```
|
||||
|
||||
赞爆了!那要是我属于一行的内容写不下想要写到第二行怎么办?
|
||||
|
||||
```ini
|
||||
[advance]
|
||||
two_lines = how about \
|
||||
continuation lines?
|
||||
lots_of_lines = 1 \
|
||||
2 \
|
||||
3 \
|
||||
4
|
||||
```
|
||||
|
||||
简直是小菜一碟!
|
||||
|
||||
```go
|
||||
cfg.Section("advance").Key("two_lines").String() // how about continuation lines?
|
||||
cfg.Section("advance").Key("lots_of_lines").String() // 1 2 3 4
|
||||
```
|
||||
|
||||
需要注意的是,值两侧的单引号会被自动剔除:
|
||||
|
||||
```ini
|
||||
foo = "some value" // foo: some value
|
||||
bar = 'some value' // bar: some value
|
||||
```
|
||||
|
||||
这就是全部了?哈哈,当然不是。
|
||||
|
||||
#### 操作键值的辅助方法
|
||||
|
||||
获取键值时设定候选值:
|
||||
|
||||
```go
|
||||
v = cfg.Section("").Key("STRING").In("default", []string{"str", "arr", "types"})
|
||||
v = cfg.Section("").Key("FLOAT64").InFloat64(1.1, []float64{1.25, 2.5, 3.75})
|
||||
v = cfg.Section("").Key("INT").InInt(5, []int{10, 20, 30})
|
||||
v = cfg.Section("").Key("INT64").InInt64(10, []int64{10, 20, 30})
|
||||
v = cfg.Section("").Key("UINT").InUint(4, []int{3, 6, 9})
|
||||
v = cfg.Section("").Key("UINT64").InUint64(8, []int64{3, 6, 9})
|
||||
v = cfg.Section("").Key("TIME").InTimeFormat(time.RFC3339, time.Now(), []time.Time{time1, time2, time3})
|
||||
v = cfg.Section("").Key("TIME").InTime(time.Now(), []time.Time{time1, time2, time3}) // RFC3339
|
||||
```
|
||||
|
||||
如果获取到的值不是候选值的任意一个,则会返回默认值,而默认值不需要是候选值中的一员。
|
||||
|
||||
验证获取的值是否在指定范围内:
|
||||
|
||||
```go
|
||||
vals = cfg.Section("").Key("FLOAT64").RangeFloat64(0.0, 1.1, 2.2)
|
||||
vals = cfg.Section("").Key("INT").RangeInt(0, 10, 20)
|
||||
vals = cfg.Section("").Key("INT64").RangeInt64(0, 10, 20)
|
||||
vals = cfg.Section("").Key("UINT").RangeUint(0, 3, 9)
|
||||
vals = cfg.Section("").Key("UINT64").RangeUint64(0, 3, 9)
|
||||
vals = cfg.Section("").Key("TIME").RangeTimeFormat(time.RFC3339, time.Now(), minTime, maxTime)
|
||||
vals = cfg.Section("").Key("TIME").RangeTime(time.Now(), minTime, maxTime) // RFC3339
|
||||
```
|
||||
|
||||
自动分割键值为切片(slice):
|
||||
|
||||
```go
|
||||
vals = cfg.Section("").Key("STRINGS").Strings(",")
|
||||
vals = cfg.Section("").Key("FLOAT64S").Float64s(",")
|
||||
vals = cfg.Section("").Key("INTS").Ints(",")
|
||||
vals = cfg.Section("").Key("INT64S").Int64s(",")
|
||||
vals = cfg.Section("").Key("UINTS").Uints(",")
|
||||
vals = cfg.Section("").Key("UINT64S").Uint64s(",")
|
||||
vals = cfg.Section("").Key("TIMES").Times(",")
|
||||
```
|
||||
|
||||
### 保存配置
|
||||
|
||||
终于到了这个时刻,是时候保存一下配置了。
|
||||
|
||||
比较原始的做法是输出配置到某个文件:
|
||||
|
||||
```go
|
||||
// ...
|
||||
err = cfg.SaveTo("my.ini")
|
||||
err = cfg.SaveToIndent("my.ini", "\t")
|
||||
```
|
||||
|
||||
另一个比较高级的做法是写入到任何实现 `io.Writer` 接口的对象中:
|
||||
|
||||
```go
|
||||
// ...
|
||||
cfg.WriteTo(writer)
|
||||
cfg.WriteToIndent(writer, "\t")
|
||||
```
|
||||
|
||||
### 高级用法
|
||||
|
||||
#### 递归读取键值
|
||||
|
||||
在获取所有键值的过程中,特殊语法 `%(<name>)s` 会被应用,其中 `<name>` 可以是相同分区或者默认分区下的键名。字符串 `%(<name>)s` 会被相应的键值所替代,如果指定的键不存在,则会用空字符串替代。您可以最多使用 99 层的递归嵌套。
|
||||
|
||||
```ini
|
||||
NAME = ini
|
||||
|
||||
[author]
|
||||
NAME = Unknwon
|
||||
GITHUB = https://github.com/%(NAME)s
|
||||
|
||||
[package]
|
||||
FULL_NAME = github.com/go-ini/%(NAME)s
|
||||
```
|
||||
|
||||
```go
|
||||
cfg.Section("author").Key("GITHUB").String() // https://github.com/Unknwon
|
||||
cfg.Section("package").Key("FULL_NAME").String() // github.com/go-ini/ini
|
||||
```
|
||||
|
||||
#### 读取父子分区
|
||||
|
||||
您可以在分区名称中使用 `.` 来表示两个或多个分区之间的父子关系。如果某个键在子分区中不存在,则会去它的父分区中再次寻找,直到没有父分区为止。
|
||||
|
||||
```ini
|
||||
NAME = ini
|
||||
VERSION = v1
|
||||
IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s
|
||||
|
||||
[package]
|
||||
CLONE_URL = https://%(IMPORT_PATH)s
|
||||
|
||||
[package.sub]
|
||||
```
|
||||
|
||||
```go
|
||||
cfg.Section("package.sub").Key("CLONE_URL").String() // https://gopkg.in/ini.v1
|
||||
```
|
||||
|
||||
#### 读取自增键名
|
||||
|
||||
如果数据源中的键名为 `-`,则认为该键使用了自增键名的特殊语法。计数器从 1 开始,并且分区之间是相互独立的。
|
||||
|
||||
```ini
|
||||
[features]
|
||||
-: Support read/write comments of keys and sections
|
||||
-: Support auto-increment of key names
|
||||
-: Support load multiple files to overwrite key values
|
||||
```
|
||||
|
||||
```go
|
||||
cfg.Section("features").KeyStrings() // []{"#1", "#2", "#3"}
|
||||
```
|
||||
|
||||
### 映射到结构
|
||||
|
||||
想要使用更加面向对象的方式玩转 INI 吗?好主意。
|
||||
|
||||
```ini
|
||||
Name = Unknwon
|
||||
age = 21
|
||||
Male = true
|
||||
Born = 1993-01-01T20:17:05Z
|
||||
|
||||
[Note]
|
||||
Content = Hi is a good man!
|
||||
Cities = HangZhou, Boston
|
||||
```
|
||||
|
||||
```go
|
||||
type Note struct {
|
||||
Content string
|
||||
Cities []string
|
||||
}
|
||||
|
||||
type Person struct {
|
||||
Name string
|
||||
Age int `ini:"age"`
|
||||
Male bool
|
||||
Born time.Time
|
||||
Note
|
||||
Created time.Time `ini:"-"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
cfg, err := ini.Load("path/to/ini")
|
||||
// ...
|
||||
p := new(Person)
|
||||
err = cfg.MapTo(p)
|
||||
// ...
|
||||
|
||||
// 一切竟可以如此的简单。
|
||||
err = ini.MapTo(p, "path/to/ini")
|
||||
// ...
|
||||
|
||||
// 嗯哼?只需要映射一个分区吗?
|
||||
n := new(Note)
|
||||
err = cfg.Section("Note").MapTo(n)
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
结构的字段怎么设置默认值呢?很简单,只要在映射之前对指定字段进行赋值就可以了。如果键未找到或者类型错误,该值不会发生改变。
|
||||
|
||||
```go
|
||||
// ...
|
||||
p := &Person{
|
||||
Name: "Joe",
|
||||
}
|
||||
// ...
|
||||
```
|
||||
|
||||
这样玩 INI 真的好酷啊!然而,如果不能还给我原来的配置文件,有什么卵用?
|
||||
|
||||
### 从结构反射
|
||||
|
||||
可是,我有说不能吗?
|
||||
|
||||
```go
|
||||
type Embeded struct {
|
||||
Dates []time.Time `delim:"|"`
|
||||
Places []string
|
||||
None []int
|
||||
}
|
||||
|
||||
type Author struct {
|
||||
Name string `ini:"NAME"`
|
||||
Male bool
|
||||
Age int
|
||||
GPA float64
|
||||
NeverMind string `ini:"-"`
|
||||
*Embeded
|
||||
}
|
||||
|
||||
func main() {
|
||||
a := &Author{"Unknwon", true, 21, 2.8, "",
|
||||
&Embeded{
|
||||
[]time.Time{time.Now(), time.Now()},
|
||||
[]string{"HangZhou", "Boston"},
|
||||
[]int{},
|
||||
}}
|
||||
cfg := ini.Empty()
|
||||
err = ini.ReflectFrom(cfg, a)
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
瞧瞧,奇迹发生了。
|
||||
|
||||
```ini
|
||||
NAME = Unknwon
|
||||
Male = true
|
||||
Age = 21
|
||||
GPA = 2.8
|
||||
|
||||
[Embeded]
|
||||
Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00
|
||||
Places = HangZhou,Boston
|
||||
None =
|
||||
```
|
||||
|
||||
#### 名称映射器(Name Mapper)
|
||||
|
||||
为了节省您的时间并简化代码,本库支持类型为 [`NameMapper`](https://gowalker.org/gopkg.in/ini.v1#NameMapper) 的名称映射器,该映射器负责结构字段名与分区名和键名之间的映射。
|
||||
|
||||
目前有 2 款内置的映射器:
|
||||
|
||||
- `AllCapsUnderscore`:该映射器将字段名转换至格式 `ALL_CAPS_UNDERSCORE` 后再去匹配分区名和键名。
|
||||
- `TitleUnderscore`:该映射器将字段名转换至格式 `title_underscore` 后再去匹配分区名和键名。
|
||||
|
||||
使用方法:
|
||||
|
||||
```go
|
||||
type Info struct{
|
||||
PackageName string
|
||||
}
|
||||
|
||||
func main() {
|
||||
err = ini.MapToWithMapper(&Info{}, ini.TitleUnderscore, []byte("packag_name=ini"))
|
||||
// ...
|
||||
|
||||
cfg, err := ini.Load([]byte("PACKAGE_NAME=ini"))
|
||||
// ...
|
||||
info := new(Info)
|
||||
cfg.NameMapper = ini.AllCapsUnderscore
|
||||
err = cfg.MapTo(info)
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
使用函数 `ini.ReflectFromWithMapper` 时也可应用相同的规则。
|
||||
|
||||
#### 映射/反射的其它说明
|
||||
|
||||
任何嵌入的结构都会被默认认作一个不同的分区,并且不会自动产生所谓的父子分区关联:
|
||||
|
||||
```go
|
||||
type Child struct {
|
||||
Age string
|
||||
}
|
||||
|
||||
type Parent struct {
|
||||
Name string
|
||||
Child
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
City string
|
||||
Parent
|
||||
}
|
||||
```
|
||||
|
||||
示例配置文件:
|
||||
|
||||
```ini
|
||||
City = Boston
|
||||
|
||||
[Parent]
|
||||
Name = Unknwon
|
||||
|
||||
[Child]
|
||||
Age = 21
|
||||
```
|
||||
|
||||
很好,但是,我就是要嵌入结构也在同一个分区。好吧,你爹是李刚!
|
||||
|
||||
```go
|
||||
type Child struct {
|
||||
Age string
|
||||
}
|
||||
|
||||
type Parent struct {
|
||||
Name string
|
||||
Child `ini:"Parent"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
City string
|
||||
Parent
|
||||
}
|
||||
```
|
||||
|
||||
示例配置文件:
|
||||
|
||||
```ini
|
||||
City = Boston
|
||||
|
||||
[Parent]
|
||||
Name = Unknwon
|
||||
Age = 21
|
||||
```
|
||||
|
||||
## 获取帮助
|
||||
|
||||
- [API 文档](https://gowalker.org/gopkg.in/ini.v1)
|
||||
- [创建工单](https://github.com/go-ini/ini/issues/new)
|
||||
|
||||
## 常见问题
|
||||
|
||||
### 字段 `BlockMode` 是什么?
|
||||
|
||||
默认情况下,本库会在您进行读写操作时采用锁机制来确保数据时间。但在某些情况下,您非常确定只进行读操作。此时,您可以通过设置 `cfg.BlockMode = false` 来将读操作提升大约 **50-70%** 的性能。
|
||||
|
||||
### 为什么要写另一个 INI 解析库?
|
||||
|
||||
许多人都在使用我的 [goconfig](https://github.com/Unknwon/goconfig) 来完成对 INI 文件的操作,但我希望使用更加 Go 风格的代码。并且当您设置 `cfg.BlockMode = false` 时,会有大约 **10-30%** 的性能提升。
|
||||
|
||||
为了做出这些改变,我必须对 API 进行破坏,所以新开一个仓库是最安全的做法。除此之外,本库直接使用 `gopkg.in` 来进行版本化发布。(其实真相是导入路径更短了)
|
1226
vendor/github.com/aws/aws-sdk-go/vendor/github.com/go-ini/ini/ini.go
generated
vendored
Normal file
1226
vendor/github.com/aws/aws-sdk-go/vendor/github.com/go-ini/ini/ini.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
350
vendor/github.com/aws/aws-sdk-go/vendor/github.com/go-ini/ini/struct.go
generated
vendored
Normal file
350
vendor/github.com/aws/aws-sdk-go/vendor/github.com/go-ini/ini/struct.go
generated
vendored
Normal file
@ -0,0 +1,350 @@
|
||||
// Copyright 2014 Unknwon
|
||||
//
|
||||
// Licensed 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 ini
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"time"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// NameMapper represents a ini tag name mapper.
|
||||
type NameMapper func(string) string
|
||||
|
||||
// Built-in name getters.
|
||||
var (
|
||||
// AllCapsUnderscore converts to format ALL_CAPS_UNDERSCORE.
|
||||
AllCapsUnderscore NameMapper = func(raw string) string {
|
||||
newstr := make([]rune, 0, len(raw))
|
||||
for i, chr := range raw {
|
||||
if isUpper := 'A' <= chr && chr <= 'Z'; isUpper {
|
||||
if i > 0 {
|
||||
newstr = append(newstr, '_')
|
||||
}
|
||||
}
|
||||
newstr = append(newstr, unicode.ToUpper(chr))
|
||||
}
|
||||
return string(newstr)
|
||||
}
|
||||
// TitleUnderscore converts to format title_underscore.
|
||||
TitleUnderscore NameMapper = func(raw string) string {
|
||||
newstr := make([]rune, 0, len(raw))
|
||||
for i, chr := range raw {
|
||||
if isUpper := 'A' <= chr && chr <= 'Z'; isUpper {
|
||||
if i > 0 {
|
||||
newstr = append(newstr, '_')
|
||||
}
|
||||
chr -= ('A' - 'a')
|
||||
}
|
||||
newstr = append(newstr, chr)
|
||||
}
|
||||
return string(newstr)
|
||||
}
|
||||
)
|
||||
|
||||
func (s *Section) parseFieldName(raw, actual string) string {
|
||||
if len(actual) > 0 {
|
||||
return actual
|
||||
}
|
||||
if s.f.NameMapper != nil {
|
||||
return s.f.NameMapper(raw)
|
||||
}
|
||||
return raw
|
||||
}
|
||||
|
||||
func parseDelim(actual string) string {
|
||||
if len(actual) > 0 {
|
||||
return actual
|
||||
}
|
||||
return ","
|
||||
}
|
||||
|
||||
var reflectTime = reflect.TypeOf(time.Now()).Kind()
|
||||
|
||||
// setWithProperType sets proper value to field based on its type,
|
||||
// but it does not return error for failing parsing,
|
||||
// because we want to use default value that is already assigned to strcut.
|
||||
func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string) error {
|
||||
switch t.Kind() {
|
||||
case reflect.String:
|
||||
if len(key.String()) == 0 {
|
||||
return nil
|
||||
}
|
||||
field.SetString(key.String())
|
||||
case reflect.Bool:
|
||||
boolVal, err := key.Bool()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
field.SetBool(boolVal)
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
durationVal, err := key.Duration()
|
||||
if err == nil {
|
||||
field.Set(reflect.ValueOf(durationVal))
|
||||
return nil
|
||||
}
|
||||
|
||||
intVal, err := key.Int64()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
field.SetInt(intVal)
|
||||
// byte is an alias for uint8, so supporting uint8 breaks support for byte
|
||||
case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
durationVal, err := key.Duration()
|
||||
if err == nil {
|
||||
field.Set(reflect.ValueOf(durationVal))
|
||||
return nil
|
||||
}
|
||||
|
||||
uintVal, err := key.Uint64()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
field.SetUint(uintVal)
|
||||
|
||||
case reflect.Float64:
|
||||
floatVal, err := key.Float64()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
field.SetFloat(floatVal)
|
||||
case reflectTime:
|
||||
timeVal, err := key.Time()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
field.Set(reflect.ValueOf(timeVal))
|
||||
case reflect.Slice:
|
||||
vals := key.Strings(delim)
|
||||
numVals := len(vals)
|
||||
if numVals == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
sliceOf := field.Type().Elem().Kind()
|
||||
|
||||
var times []time.Time
|
||||
if sliceOf == reflectTime {
|
||||
times = key.Times(delim)
|
||||
}
|
||||
|
||||
slice := reflect.MakeSlice(field.Type(), numVals, numVals)
|
||||
for i := 0; i < numVals; i++ {
|
||||
switch sliceOf {
|
||||
case reflectTime:
|
||||
slice.Index(i).Set(reflect.ValueOf(times[i]))
|
||||
default:
|
||||
slice.Index(i).Set(reflect.ValueOf(vals[i]))
|
||||
}
|
||||
}
|
||||
field.Set(slice)
|
||||
default:
|
||||
return fmt.Errorf("unsupported type '%s'", t)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Section) mapTo(val reflect.Value) error {
|
||||
if val.Kind() == reflect.Ptr {
|
||||
val = val.Elem()
|
||||
}
|
||||
typ := val.Type()
|
||||
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
field := val.Field(i)
|
||||
tpField := typ.Field(i)
|
||||
|
||||
tag := tpField.Tag.Get("ini")
|
||||
if tag == "-" {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldName := s.parseFieldName(tpField.Name, tag)
|
||||
if len(fieldName) == 0 || !field.CanSet() {
|
||||
continue
|
||||
}
|
||||
|
||||
isAnonymous := tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous
|
||||
isStruct := tpField.Type.Kind() == reflect.Struct
|
||||
if isAnonymous {
|
||||
field.Set(reflect.New(tpField.Type.Elem()))
|
||||
}
|
||||
|
||||
if isAnonymous || isStruct {
|
||||
if sec, err := s.f.GetSection(fieldName); err == nil {
|
||||
if err = sec.mapTo(field); err != nil {
|
||||
return fmt.Errorf("error mapping field(%s): %v", fieldName, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if key, err := s.GetKey(fieldName); err == nil {
|
||||
if err = setWithProperType(tpField.Type, key, field, parseDelim(tpField.Tag.Get("delim"))); err != nil {
|
||||
return fmt.Errorf("error mapping field(%s): %v", fieldName, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MapTo maps section to given struct.
|
||||
func (s *Section) MapTo(v interface{}) error {
|
||||
typ := reflect.TypeOf(v)
|
||||
val := reflect.ValueOf(v)
|
||||
if typ.Kind() == reflect.Ptr {
|
||||
typ = typ.Elem()
|
||||
val = val.Elem()
|
||||
} else {
|
||||
return errors.New("cannot map to non-pointer struct")
|
||||
}
|
||||
|
||||
return s.mapTo(val)
|
||||
}
|
||||
|
||||
// MapTo maps file to given struct.
|
||||
func (f *File) MapTo(v interface{}) error {
|
||||
return f.Section("").MapTo(v)
|
||||
}
|
||||
|
||||
// MapTo maps data sources to given struct with name mapper.
|
||||
func MapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error {
|
||||
cfg, err := Load(source, others...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfg.NameMapper = mapper
|
||||
return cfg.MapTo(v)
|
||||
}
|
||||
|
||||
// MapTo maps data sources to given struct.
|
||||
func MapTo(v, source interface{}, others ...interface{}) error {
|
||||
return MapToWithMapper(v, nil, source, others...)
|
||||
}
|
||||
|
||||
// reflectWithProperType does the opposite thing with setWithProperType.
|
||||
func reflectWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string) error {
|
||||
switch t.Kind() {
|
||||
case reflect.String:
|
||||
key.SetValue(field.String())
|
||||
case reflect.Bool,
|
||||
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
||||
reflect.Float64,
|
||||
reflectTime:
|
||||
key.SetValue(fmt.Sprint(field))
|
||||
case reflect.Slice:
|
||||
vals := field.Slice(0, field.Len())
|
||||
if field.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
isTime := fmt.Sprint(field.Type()) == "[]time.Time"
|
||||
for i := 0; i < field.Len(); i++ {
|
||||
if isTime {
|
||||
buf.WriteString(vals.Index(i).Interface().(time.Time).Format(time.RFC3339))
|
||||
} else {
|
||||
buf.WriteString(fmt.Sprint(vals.Index(i)))
|
||||
}
|
||||
buf.WriteString(delim)
|
||||
}
|
||||
key.SetValue(buf.String()[:buf.Len()-1])
|
||||
default:
|
||||
return fmt.Errorf("unsupported type '%s'", t)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Section) reflectFrom(val reflect.Value) error {
|
||||
if val.Kind() == reflect.Ptr {
|
||||
val = val.Elem()
|
||||
}
|
||||
typ := val.Type()
|
||||
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
field := val.Field(i)
|
||||
tpField := typ.Field(i)
|
||||
|
||||
tag := tpField.Tag.Get("ini")
|
||||
if tag == "-" {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldName := s.parseFieldName(tpField.Name, tag)
|
||||
if len(fieldName) == 0 || !field.CanSet() {
|
||||
continue
|
||||
}
|
||||
|
||||
if (tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous) ||
|
||||
(tpField.Type.Kind() == reflect.Struct) {
|
||||
// Note: The only error here is section doesn't exist.
|
||||
sec, err := s.f.GetSection(fieldName)
|
||||
if err != nil {
|
||||
// Note: fieldName can never be empty here, ignore error.
|
||||
sec, _ = s.f.NewSection(fieldName)
|
||||
}
|
||||
if err = sec.reflectFrom(field); err != nil {
|
||||
return fmt.Errorf("error reflecting field(%s): %v", fieldName, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Note: Same reason as secion.
|
||||
key, err := s.GetKey(fieldName)
|
||||
if err != nil {
|
||||
key, _ = s.NewKey(fieldName, "")
|
||||
}
|
||||
if err = reflectWithProperType(tpField.Type, key, field, parseDelim(tpField.Tag.Get("delim"))); err != nil {
|
||||
return fmt.Errorf("error reflecting field(%s): %v", fieldName, err)
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReflectFrom reflects secion from given struct.
|
||||
func (s *Section) ReflectFrom(v interface{}) error {
|
||||
typ := reflect.TypeOf(v)
|
||||
val := reflect.ValueOf(v)
|
||||
if typ.Kind() == reflect.Ptr {
|
||||
typ = typ.Elem()
|
||||
val = val.Elem()
|
||||
} else {
|
||||
return errors.New("cannot reflect from non-pointer struct")
|
||||
}
|
||||
|
||||
return s.reflectFrom(val)
|
||||
}
|
||||
|
||||
// ReflectFrom reflects file from given struct.
|
||||
func (f *File) ReflectFrom(v interface{}) error {
|
||||
return f.Section("").ReflectFrom(v)
|
||||
}
|
||||
|
||||
// ReflectFrom reflects data sources from given struct with name mapper.
|
||||
func ReflectFromWithMapper(cfg *File, v interface{}, mapper NameMapper) error {
|
||||
cfg.NameMapper = mapper
|
||||
return cfg.ReflectFrom(v)
|
||||
}
|
||||
|
||||
// ReflectFrom reflects data sources from given struct.
|
||||
func ReflectFrom(cfg *File, v interface{}) error {
|
||||
return ReflectFromWithMapper(cfg, v, nil)
|
||||
}
|
4
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/.gitignore
generated
vendored
Normal file
4
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/.gitignore
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
jpgo
|
||||
jmespath-fuzz.zip
|
||||
cpu.out
|
||||
go-jmespath.test
|
9
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/.travis.yml
generated
vendored
Normal file
9
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
language: go
|
||||
|
||||
sudo: false
|
||||
|
||||
go:
|
||||
- 1.4
|
||||
|
||||
install: go get -v -t ./...
|
||||
script: make test
|
13
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/LICENSE
generated
vendored
Normal file
13
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/LICENSE
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
Copyright 2015 James Saryerwinnie
|
||||
|
||||
Licensed 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.
|
44
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/Makefile
generated
vendored
Normal file
44
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/Makefile
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
|
||||
CMD = jpgo
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " test to run all the tests"
|
||||
@echo " build to build the library and jp executable"
|
||||
@echo " generate to run codegen"
|
||||
|
||||
|
||||
generate:
|
||||
go generate ./...
|
||||
|
||||
build:
|
||||
rm -f $(CMD)
|
||||
go build ./...
|
||||
rm -f cmd/$(CMD)/$(CMD) && cd cmd/$(CMD)/ && go build ./...
|
||||
mv cmd/$(CMD)/$(CMD) .
|
||||
|
||||
test:
|
||||
go test -v ./...
|
||||
|
||||
check:
|
||||
go vet ./...
|
||||
@echo "golint ./..."
|
||||
@lint=`golint ./...`; \
|
||||
lint=`echo "$$lint" | grep -v "astnodetype_string.go" | grep -v "toktype_string.go"`; \
|
||||
echo "$$lint"; \
|
||||
if [ "$$lint" != "" ]; then exit 1; fi
|
||||
|
||||
htmlc:
|
||||
go test -coverprofile="/tmp/jpcov" && go tool cover -html="/tmp/jpcov" && unlink /tmp/jpcov
|
||||
|
||||
buildfuzz:
|
||||
go-fuzz-build github.com/jmespath/go-jmespath/fuzz
|
||||
|
||||
fuzz: buildfuzz
|
||||
go-fuzz -bin=./jmespath-fuzz.zip -workdir=fuzz/corpus
|
||||
|
||||
bench:
|
||||
go test -bench . -cpuprofile cpu.out
|
||||
|
||||
pprof-cpu:
|
||||
go tool pprof ./go-jmespath.test ./cpu.out
|
7
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/README.md
generated
vendored
Normal file
7
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/README.md
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
# go-jmespath - A JMESPath implementation in Go
|
||||
|
||||
[](https://travis-ci.org/jmespath/go-jmespath)
|
||||
|
||||
|
||||
|
||||
See http://jmespath.org for more info.
|
12
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/api.go
generated
vendored
Normal file
12
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/api.go
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
package jmespath
|
||||
|
||||
// Search evaluates a JMESPath expression against input data and returns the result.
|
||||
func Search(expression string, data interface{}) (interface{}, error) {
|
||||
intr := newInterpreter()
|
||||
parser := NewParser()
|
||||
ast, err := parser.Parse(expression)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return intr.Execute(ast, data)
|
||||
}
|
16
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/astnodetype_string.go
generated
vendored
Normal file
16
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/astnodetype_string.go
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
// generated by stringer -type astNodeType; DO NOT EDIT
|
||||
|
||||
package jmespath
|
||||
|
||||
import "fmt"
|
||||
|
||||
const _astNodeType_name = "ASTEmptyASTComparatorASTCurrentNodeASTExpRefASTFunctionExpressionASTFieldASTFilterProjectionASTFlattenASTIdentityASTIndexASTIndexExpressionASTKeyValPairASTLiteralASTMultiSelectHashASTMultiSelectListASTOrExpressionASTAndExpressionASTNotExpressionASTPipeASTProjectionASTSubexpressionASTSliceASTValueProjection"
|
||||
|
||||
var _astNodeType_index = [...]uint16{0, 8, 21, 35, 44, 65, 73, 92, 102, 113, 121, 139, 152, 162, 180, 198, 213, 229, 245, 252, 265, 281, 289, 307}
|
||||
|
||||
func (i astNodeType) String() string {
|
||||
if i < 0 || i >= astNodeType(len(_astNodeType_index)-1) {
|
||||
return fmt.Sprintf("astNodeType(%d)", i)
|
||||
}
|
||||
return _astNodeType_name[_astNodeType_index[i]:_astNodeType_index[i+1]]
|
||||
}
|
840
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/functions.go
generated
vendored
Normal file
840
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/functions.go
generated
vendored
Normal file
@ -0,0 +1,840 @@
|
||||
package jmespath
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type jpFunction func(arguments []interface{}) (interface{}, error)
|
||||
|
||||
type jpType string
|
||||
|
||||
const (
|
||||
jpUnknown jpType = "unknown"
|
||||
jpNumber jpType = "number"
|
||||
jpString jpType = "string"
|
||||
jpArray jpType = "array"
|
||||
jpObject jpType = "object"
|
||||
jpArrayNumber jpType = "array[number]"
|
||||
jpArrayString jpType = "array[string]"
|
||||
jpExpref jpType = "expref"
|
||||
jpAny jpType = "any"
|
||||
)
|
||||
|
||||
type functionEntry struct {
|
||||
name string
|
||||
arguments []argSpec
|
||||
handler jpFunction
|
||||
hasExpRef bool
|
||||
}
|
||||
|
||||
type argSpec struct {
|
||||
types []jpType
|
||||
variadic bool
|
||||
}
|
||||
|
||||
type byExprString struct {
|
||||
intr *treeInterpreter
|
||||
node ASTNode
|
||||
items []interface{}
|
||||
hasError bool
|
||||
}
|
||||
|
||||
func (a *byExprString) Len() int {
|
||||
return len(a.items)
|
||||
}
|
||||
func (a *byExprString) Swap(i, j int) {
|
||||
a.items[i], a.items[j] = a.items[j], a.items[i]
|
||||
}
|
||||
func (a *byExprString) Less(i, j int) bool {
|
||||
first, err := a.intr.Execute(a.node, a.items[i])
|
||||
if err != nil {
|
||||
a.hasError = true
|
||||
// Return a dummy value.
|
||||
return true
|
||||
}
|
||||
ith, ok := first.(string)
|
||||
if !ok {
|
||||
a.hasError = true
|
||||
return true
|
||||
}
|
||||
second, err := a.intr.Execute(a.node, a.items[j])
|
||||
if err != nil {
|
||||
a.hasError = true
|
||||
// Return a dummy value.
|
||||
return true
|
||||
}
|
||||
jth, ok := second.(string)
|
||||
if !ok {
|
||||
a.hasError = true
|
||||
return true
|
||||
}
|
||||
return ith < jth
|
||||
}
|
||||
|
||||
type byExprFloat struct {
|
||||
intr *treeInterpreter
|
||||
node ASTNode
|
||||
items []interface{}
|
||||
hasError bool
|
||||
}
|
||||
|
||||
func (a *byExprFloat) Len() int {
|
||||
return len(a.items)
|
||||
}
|
||||
func (a *byExprFloat) Swap(i, j int) {
|
||||
a.items[i], a.items[j] = a.items[j], a.items[i]
|
||||
}
|
||||
func (a *byExprFloat) Less(i, j int) bool {
|
||||
first, err := a.intr.Execute(a.node, a.items[i])
|
||||
if err != nil {
|
||||
a.hasError = true
|
||||
// Return a dummy value.
|
||||
return true
|
||||
}
|
||||
ith, ok := first.(float64)
|
||||
if !ok {
|
||||
a.hasError = true
|
||||
return true
|
||||
}
|
||||
second, err := a.intr.Execute(a.node, a.items[j])
|
||||
if err != nil {
|
||||
a.hasError = true
|
||||
// Return a dummy value.
|
||||
return true
|
||||
}
|
||||
jth, ok := second.(float64)
|
||||
if !ok {
|
||||
a.hasError = true
|
||||
return true
|
||||
}
|
||||
return ith < jth
|
||||
}
|
||||
|
||||
type functionCaller struct {
|
||||
functionTable map[string]functionEntry
|
||||
}
|
||||
|
||||
func newFunctionCaller() *functionCaller {
|
||||
caller := &functionCaller{}
|
||||
caller.functionTable = map[string]functionEntry{
|
||||
"length": functionEntry{
|
||||
name: "length",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpString, jpArray, jpObject}},
|
||||
},
|
||||
handler: jpfLength,
|
||||
},
|
||||
"starts_with": functionEntry{
|
||||
name: "starts_with",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpString}},
|
||||
argSpec{types: []jpType{jpString}},
|
||||
},
|
||||
handler: jpfStartsWith,
|
||||
},
|
||||
"abs": functionEntry{
|
||||
name: "abs",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpNumber}},
|
||||
},
|
||||
handler: jpfAbs,
|
||||
},
|
||||
"avg": functionEntry{
|
||||
name: "avg",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpArrayNumber}},
|
||||
},
|
||||
handler: jpfAvg,
|
||||
},
|
||||
"ceil": functionEntry{
|
||||
name: "ceil",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpNumber}},
|
||||
},
|
||||
handler: jpfCeil,
|
||||
},
|
||||
"contains": functionEntry{
|
||||
name: "contains",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpArray, jpString}},
|
||||
argSpec{types: []jpType{jpAny}},
|
||||
},
|
||||
handler: jpfContains,
|
||||
},
|
||||
"ends_with": functionEntry{
|
||||
name: "ends_with",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpString}},
|
||||
argSpec{types: []jpType{jpString}},
|
||||
},
|
||||
handler: jpfEndsWith,
|
||||
},
|
||||
"floor": functionEntry{
|
||||
name: "floor",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpNumber}},
|
||||
},
|
||||
handler: jpfFloor,
|
||||
},
|
||||
"map": functionEntry{
|
||||
name: "amp",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpExpref}},
|
||||
argSpec{types: []jpType{jpArray}},
|
||||
},
|
||||
handler: jpfMap,
|
||||
hasExpRef: true,
|
||||
},
|
||||
"max": functionEntry{
|
||||
name: "max",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpArrayNumber, jpArrayString}},
|
||||
},
|
||||
handler: jpfMax,
|
||||
},
|
||||
"merge": functionEntry{
|
||||
name: "merge",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpObject}, variadic: true},
|
||||
},
|
||||
handler: jpfMerge,
|
||||
},
|
||||
"max_by": functionEntry{
|
||||
name: "max_by",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpArray}},
|
||||
argSpec{types: []jpType{jpExpref}},
|
||||
},
|
||||
handler: jpfMaxBy,
|
||||
hasExpRef: true,
|
||||
},
|
||||
"sum": functionEntry{
|
||||
name: "sum",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpArrayNumber}},
|
||||
},
|
||||
handler: jpfSum,
|
||||
},
|
||||
"min": functionEntry{
|
||||
name: "min",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpArrayNumber, jpArrayString}},
|
||||
},
|
||||
handler: jpfMin,
|
||||
},
|
||||
"min_by": functionEntry{
|
||||
name: "min_by",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpArray}},
|
||||
argSpec{types: []jpType{jpExpref}},
|
||||
},
|
||||
handler: jpfMinBy,
|
||||
hasExpRef: true,
|
||||
},
|
||||
"type": functionEntry{
|
||||
name: "type",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpAny}},
|
||||
},
|
||||
handler: jpfType,
|
||||
},
|
||||
"keys": functionEntry{
|
||||
name: "keys",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpObject}},
|
||||
},
|
||||
handler: jpfKeys,
|
||||
},
|
||||
"values": functionEntry{
|
||||
name: "values",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpObject}},
|
||||
},
|
||||
handler: jpfValues,
|
||||
},
|
||||
"sort": functionEntry{
|
||||
name: "sort",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpArrayString, jpArrayNumber}},
|
||||
},
|
||||
handler: jpfSort,
|
||||
},
|
||||
"sort_by": functionEntry{
|
||||
name: "sort_by",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpArray}},
|
||||
argSpec{types: []jpType{jpExpref}},
|
||||
},
|
||||
handler: jpfSortBy,
|
||||
hasExpRef: true,
|
||||
},
|
||||
"join": functionEntry{
|
||||
name: "join",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpString}},
|
||||
argSpec{types: []jpType{jpArrayString}},
|
||||
},
|
||||
handler: jpfJoin,
|
||||
},
|
||||
"reverse": functionEntry{
|
||||
name: "reverse",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpArray, jpString}},
|
||||
},
|
||||
handler: jpfReverse,
|
||||
},
|
||||
"to_array": functionEntry{
|
||||
name: "to_array",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpAny}},
|
||||
},
|
||||
handler: jpfToArray,
|
||||
},
|
||||
"to_string": functionEntry{
|
||||
name: "to_string",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpAny}},
|
||||
},
|
||||
handler: jpfToString,
|
||||
},
|
||||
"to_number": functionEntry{
|
||||
name: "to_number",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpAny}},
|
||||
},
|
||||
handler: jpfToNumber,
|
||||
},
|
||||
"not_null": functionEntry{
|
||||
name: "not_null",
|
||||
arguments: []argSpec{
|
||||
argSpec{types: []jpType{jpAny}, variadic: true},
|
||||
},
|
||||
handler: jpfNotNull,
|
||||
},
|
||||
}
|
||||
return caller
|
||||
}
|
||||
|
||||
func (e *functionEntry) resolveArgs(arguments []interface{}) ([]interface{}, error) {
|
||||
if len(e.arguments) == 0 {
|
||||
return arguments, nil
|
||||
}
|
||||
if !e.arguments[len(e.arguments)-1].variadic {
|
||||
if len(e.arguments) != len(arguments) {
|
||||
return nil, errors.New("incorrect number of args")
|
||||
}
|
||||
for i, spec := range e.arguments {
|
||||
userArg := arguments[i]
|
||||
err := spec.typeCheck(userArg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return arguments, nil
|
||||
}
|
||||
if len(arguments) < len(e.arguments) {
|
||||
return nil, errors.New("Invalid arity.")
|
||||
}
|
||||
return arguments, nil
|
||||
}
|
||||
|
||||
func (a *argSpec) typeCheck(arg interface{}) error {
|
||||
for _, t := range a.types {
|
||||
switch t {
|
||||
case jpNumber:
|
||||
if _, ok := arg.(float64); ok {
|
||||
return nil
|
||||
}
|
||||
case jpString:
|
||||
if _, ok := arg.(string); ok {
|
||||
return nil
|
||||
}
|
||||
case jpArray:
|
||||
if _, ok := arg.([]interface{}); ok {
|
||||
return nil
|
||||
}
|
||||
case jpObject:
|
||||
if _, ok := arg.(map[string]interface{}); ok {
|
||||
return nil
|
||||
}
|
||||
case jpArrayNumber:
|
||||
if _, ok := toArrayNum(arg); ok {
|
||||
return nil
|
||||
}
|
||||
case jpArrayString:
|
||||
if _, ok := toArrayStr(arg); ok {
|
||||
return nil
|
||||
}
|
||||
case jpAny:
|
||||
return nil
|
||||
case jpExpref:
|
||||
if _, ok := arg.(expRef); ok {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("Invalid type for: %v, expected: %#v", arg, a.types)
|
||||
}
|
||||
|
||||
func (f *functionCaller) CallFunction(name string, arguments []interface{}, intr *treeInterpreter) (interface{}, error) {
|
||||
entry, ok := f.functionTable[name]
|
||||
if !ok {
|
||||
return nil, errors.New("unknown function: " + name)
|
||||
}
|
||||
resolvedArgs, err := entry.resolveArgs(arguments)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if entry.hasExpRef {
|
||||
var extra []interface{}
|
||||
extra = append(extra, intr)
|
||||
resolvedArgs = append(extra, resolvedArgs...)
|
||||
}
|
||||
return entry.handler(resolvedArgs)
|
||||
}
|
||||
|
||||
func jpfAbs(arguments []interface{}) (interface{}, error) {
|
||||
num := arguments[0].(float64)
|
||||
return math.Abs(num), nil
|
||||
}
|
||||
|
||||
func jpfLength(arguments []interface{}) (interface{}, error) {
|
||||
arg := arguments[0]
|
||||
if c, ok := arg.(string); ok {
|
||||
return float64(utf8.RuneCountInString(c)), nil
|
||||
} else if c, ok := arg.([]interface{}); ok {
|
||||
return float64(len(c)), nil
|
||||
} else if c, ok := arg.(map[string]interface{}); ok {
|
||||
return float64(len(c)), nil
|
||||
}
|
||||
return nil, errors.New("could not compute length()")
|
||||
}
|
||||
|
||||
func jpfStartsWith(arguments []interface{}) (interface{}, error) {
|
||||
search := arguments[0].(string)
|
||||
prefix := arguments[1].(string)
|
||||
return strings.HasPrefix(search, prefix), nil
|
||||
}
|
||||
|
||||
func jpfAvg(arguments []interface{}) (interface{}, error) {
|
||||
// We've already type checked the value so we can safely use
|
||||
// type assertions.
|
||||
args := arguments[0].([]interface{})
|
||||
length := float64(len(args))
|
||||
numerator := 0.0
|
||||
for _, n := range args {
|
||||
numerator += n.(float64)
|
||||
}
|
||||
return numerator / length, nil
|
||||
}
|
||||
func jpfCeil(arguments []interface{}) (interface{}, error) {
|
||||
val := arguments[0].(float64)
|
||||
return math.Ceil(val), nil
|
||||
}
|
||||
func jpfContains(arguments []interface{}) (interface{}, error) {
|
||||
search := arguments[0]
|
||||
el := arguments[1]
|
||||
if searchStr, ok := search.(string); ok {
|
||||
if elStr, ok := el.(string); ok {
|
||||
return strings.Index(searchStr, elStr) != -1, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
// Otherwise this is a generic contains for []interface{}
|
||||
general := search.([]interface{})
|
||||
for _, item := range general {
|
||||
if item == el {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
func jpfEndsWith(arguments []interface{}) (interface{}, error) {
|
||||
search := arguments[0].(string)
|
||||
suffix := arguments[1].(string)
|
||||
return strings.HasSuffix(search, suffix), nil
|
||||
}
|
||||
func jpfFloor(arguments []interface{}) (interface{}, error) {
|
||||
val := arguments[0].(float64)
|
||||
return math.Floor(val), nil
|
||||
}
|
||||
func jpfMap(arguments []interface{}) (interface{}, error) {
|
||||
intr := arguments[0].(*treeInterpreter)
|
||||
exp := arguments[1].(expRef)
|
||||
node := exp.ref
|
||||
arr := arguments[2].([]interface{})
|
||||
mapped := make([]interface{}, 0, len(arr))
|
||||
for _, value := range arr {
|
||||
current, err := intr.Execute(node, value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mapped = append(mapped, current)
|
||||
}
|
||||
return mapped, nil
|
||||
}
|
||||
func jpfMax(arguments []interface{}) (interface{}, error) {
|
||||
if items, ok := toArrayNum(arguments[0]); ok {
|
||||
if len(items) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
if len(items) == 1 {
|
||||
return items[0], nil
|
||||
}
|
||||
best := items[0]
|
||||
for _, item := range items[1:] {
|
||||
if item > best {
|
||||
best = item
|
||||
}
|
||||
}
|
||||
return best, nil
|
||||
}
|
||||
// Otherwise we're dealing with a max() of strings.
|
||||
items, _ := toArrayStr(arguments[0])
|
||||
if len(items) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
if len(items) == 1 {
|
||||
return items[0], nil
|
||||
}
|
||||
best := items[0]
|
||||
for _, item := range items[1:] {
|
||||
if item > best {
|
||||
best = item
|
||||
}
|
||||
}
|
||||
return best, nil
|
||||
}
|
||||
func jpfMerge(arguments []interface{}) (interface{}, error) {
|
||||
final := make(map[string]interface{})
|
||||
for _, m := range arguments {
|
||||
mapped := m.(map[string]interface{})
|
||||
for key, value := range mapped {
|
||||
final[key] = value
|
||||
}
|
||||
}
|
||||
return final, nil
|
||||
}
|
||||
func jpfMaxBy(arguments []interface{}) (interface{}, error) {
|
||||
intr := arguments[0].(*treeInterpreter)
|
||||
arr := arguments[1].([]interface{})
|
||||
exp := arguments[2].(expRef)
|
||||
node := exp.ref
|
||||
if len(arr) == 0 {
|
||||
return nil, nil
|
||||
} else if len(arr) == 1 {
|
||||
return arr[0], nil
|
||||
}
|
||||
start, err := intr.Execute(node, arr[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch t := start.(type) {
|
||||
case float64:
|
||||
bestVal := t
|
||||
bestItem := arr[0]
|
||||
for _, item := range arr[1:] {
|
||||
result, err := intr.Execute(node, item)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
current, ok := result.(float64)
|
||||
if !ok {
|
||||
return nil, errors.New("invalid type, must be number")
|
||||
}
|
||||
if current > bestVal {
|
||||
bestVal = current
|
||||
bestItem = item
|
||||
}
|
||||
}
|
||||
return bestItem, nil
|
||||
case string:
|
||||
bestVal := t
|
||||
bestItem := arr[0]
|
||||
for _, item := range arr[1:] {
|
||||
result, err := intr.Execute(node, item)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
current, ok := result.(string)
|
||||
if !ok {
|
||||
return nil, errors.New("invalid type, must be string")
|
||||
}
|
||||
if current > bestVal {
|
||||
bestVal = current
|
||||
bestItem = item
|
||||
}
|
||||
}
|
||||
return bestItem, nil
|
||||
default:
|
||||
return nil, errors.New("invalid type, must be number of string")
|
||||
}
|
||||
}
|
||||
func jpfSum(arguments []interface{}) (interface{}, error) {
|
||||
items, _ := toArrayNum(arguments[0])
|
||||
sum := 0.0
|
||||
for _, item := range items {
|
||||
sum += item
|
||||
}
|
||||
return sum, nil
|
||||
}
|
||||
|
||||
func jpfMin(arguments []interface{}) (interface{}, error) {
|
||||
if items, ok := toArrayNum(arguments[0]); ok {
|
||||
if len(items) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
if len(items) == 1 {
|
||||
return items[0], nil
|
||||
}
|
||||
best := items[0]
|
||||
for _, item := range items[1:] {
|
||||
if item < best {
|
||||
best = item
|
||||
}
|
||||
}
|
||||
return best, nil
|
||||
}
|
||||
items, _ := toArrayStr(arguments[0])
|
||||
if len(items) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
if len(items) == 1 {
|
||||
return items[0], nil
|
||||
}
|
||||
best := items[0]
|
||||
for _, item := range items[1:] {
|
||||
if item < best {
|
||||
best = item
|
||||
}
|
||||
}
|
||||
return best, nil
|
||||
}
|
||||
|
||||
func jpfMinBy(arguments []interface{}) (interface{}, error) {
|
||||
intr := arguments[0].(*treeInterpreter)
|
||||
arr := arguments[1].([]interface{})
|
||||
exp := arguments[2].(expRef)
|
||||
node := exp.ref
|
||||
if len(arr) == 0 {
|
||||
return nil, nil
|
||||
} else if len(arr) == 1 {
|
||||
return arr[0], nil
|
||||
}
|
||||
start, err := intr.Execute(node, arr[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if t, ok := start.(float64); ok {
|
||||
bestVal := t
|
||||
bestItem := arr[0]
|
||||
for _, item := range arr[1:] {
|
||||
result, err := intr.Execute(node, item)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
current, ok := result.(float64)
|
||||
if !ok {
|
||||
return nil, errors.New("invalid type, must be number")
|
||||
}
|
||||
if current < bestVal {
|
||||
bestVal = current
|
||||
bestItem = item
|
||||
}
|
||||
}
|
||||
return bestItem, nil
|
||||
} else if t, ok := start.(string); ok {
|
||||
bestVal := t
|
||||
bestItem := arr[0]
|
||||
for _, item := range arr[1:] {
|
||||
result, err := intr.Execute(node, item)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
current, ok := result.(string)
|
||||
if !ok {
|
||||
return nil, errors.New("invalid type, must be string")
|
||||
}
|
||||
if current < bestVal {
|
||||
bestVal = current
|
||||
bestItem = item
|
||||
}
|
||||
}
|
||||
return bestItem, nil
|
||||
} else {
|
||||
return nil, errors.New("invalid type, must be number of string")
|
||||
}
|
||||
}
|
||||
func jpfType(arguments []interface{}) (interface{}, error) {
|
||||
arg := arguments[0]
|
||||
if _, ok := arg.(float64); ok {
|
||||
return "number", nil
|
||||
}
|
||||
if _, ok := arg.(string); ok {
|
||||
return "string", nil
|
||||
}
|
||||
if _, ok := arg.([]interface{}); ok {
|
||||
return "array", nil
|
||||
}
|
||||
if _, ok := arg.(map[string]interface{}); ok {
|
||||
return "object", nil
|
||||
}
|
||||
if arg == nil {
|
||||
return "null", nil
|
||||
}
|
||||
if arg == true || arg == false {
|
||||
return "boolean", nil
|
||||
}
|
||||
return nil, errors.New("unknown type")
|
||||
}
|
||||
func jpfKeys(arguments []interface{}) (interface{}, error) {
|
||||
arg := arguments[0].(map[string]interface{})
|
||||
collected := make([]interface{}, 0, len(arg))
|
||||
for key := range arg {
|
||||
collected = append(collected, key)
|
||||
}
|
||||
return collected, nil
|
||||
}
|
||||
func jpfValues(arguments []interface{}) (interface{}, error) {
|
||||
arg := arguments[0].(map[string]interface{})
|
||||
collected := make([]interface{}, 0, len(arg))
|
||||
for _, value := range arg {
|
||||
collected = append(collected, value)
|
||||
}
|
||||
return collected, nil
|
||||
}
|
||||
func jpfSort(arguments []interface{}) (interface{}, error) {
|
||||
if items, ok := toArrayNum(arguments[0]); ok {
|
||||
d := sort.Float64Slice(items)
|
||||
sort.Stable(d)
|
||||
final := make([]interface{}, len(d))
|
||||
for i, val := range d {
|
||||
final[i] = val
|
||||
}
|
||||
return final, nil
|
||||
}
|
||||
// Otherwise we're dealing with sort()'ing strings.
|
||||
items, _ := toArrayStr(arguments[0])
|
||||
d := sort.StringSlice(items)
|
||||
sort.Stable(d)
|
||||
final := make([]interface{}, len(d))
|
||||
for i, val := range d {
|
||||
final[i] = val
|
||||
}
|
||||
return final, nil
|
||||
}
|
||||
func jpfSortBy(arguments []interface{}) (interface{}, error) {
|
||||
intr := arguments[0].(*treeInterpreter)
|
||||
arr := arguments[1].([]interface{})
|
||||
exp := arguments[2].(expRef)
|
||||
node := exp.ref
|
||||
if len(arr) == 0 {
|
||||
return arr, nil
|
||||
} else if len(arr) == 1 {
|
||||
return arr, nil
|
||||
}
|
||||
start, err := intr.Execute(node, arr[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, ok := start.(float64); ok {
|
||||
sortable := &byExprFloat{intr, node, arr, false}
|
||||
sort.Stable(sortable)
|
||||
if sortable.hasError {
|
||||
return nil, errors.New("error in sort_by comparison")
|
||||
}
|
||||
return arr, nil
|
||||
} else if _, ok := start.(string); ok {
|
||||
sortable := &byExprString{intr, node, arr, false}
|
||||
sort.Stable(sortable)
|
||||
if sortable.hasError {
|
||||
return nil, errors.New("error in sort_by comparison")
|
||||
}
|
||||
return arr, nil
|
||||
} else {
|
||||
return nil, errors.New("invalid type, must be number of string")
|
||||
}
|
||||
}
|
||||
func jpfJoin(arguments []interface{}) (interface{}, error) {
|
||||
sep := arguments[0].(string)
|
||||
// We can't just do arguments[1].([]string), we have to
|
||||
// manually convert each item to a string.
|
||||
arrayStr := []string{}
|
||||
for _, item := range arguments[1].([]interface{}) {
|
||||
arrayStr = append(arrayStr, item.(string))
|
||||
}
|
||||
return strings.Join(arrayStr, sep), nil
|
||||
}
|
||||
func jpfReverse(arguments []interface{}) (interface{}, error) {
|
||||
if s, ok := arguments[0].(string); ok {
|
||||
r := []rune(s)
|
||||
for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
|
||||
r[i], r[j] = r[j], r[i]
|
||||
}
|
||||
return string(r), nil
|
||||
}
|
||||
items := arguments[0].([]interface{})
|
||||
length := len(items)
|
||||
reversed := make([]interface{}, length)
|
||||
for i, item := range items {
|
||||
reversed[length-(i+1)] = item
|
||||
}
|
||||
return reversed, nil
|
||||
}
|
||||
func jpfToArray(arguments []interface{}) (interface{}, error) {
|
||||
if _, ok := arguments[0].([]interface{}); ok {
|
||||
return arguments[0], nil
|
||||
}
|
||||
return arguments[:1:1], nil
|
||||
}
|
||||
func jpfToString(arguments []interface{}) (interface{}, error) {
|
||||
if v, ok := arguments[0].(string); ok {
|
||||
return v, nil
|
||||
}
|
||||
result, err := json.Marshal(arguments[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return string(result), nil
|
||||
}
|
||||
func jpfToNumber(arguments []interface{}) (interface{}, error) {
|
||||
arg := arguments[0]
|
||||
if v, ok := arg.(float64); ok {
|
||||
return v, nil
|
||||
}
|
||||
if v, ok := arg.(string); ok {
|
||||
conv, err := strconv.ParseFloat(v, 64)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
return conv, nil
|
||||
}
|
||||
if _, ok := arg.([]interface{}); ok {
|
||||
return nil, nil
|
||||
}
|
||||
if _, ok := arg.(map[string]interface{}); ok {
|
||||
return nil, nil
|
||||
}
|
||||
if arg == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if arg == true || arg == false {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, errors.New("unknown type")
|
||||
}
|
||||
func jpfNotNull(arguments []interface{}) (interface{}, error) {
|
||||
for _, arg := range arguments {
|
||||
if arg != nil {
|
||||
return arg, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
418
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/interpreter.go
generated
vendored
Normal file
418
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/interpreter.go
generated
vendored
Normal file
@ -0,0 +1,418 @@
|
||||
package jmespath
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
/* This is a tree based interpreter. It walks the AST and directly
|
||||
interprets the AST to search through a JSON document.
|
||||
*/
|
||||
|
||||
type treeInterpreter struct {
|
||||
fCall *functionCaller
|
||||
}
|
||||
|
||||
func newInterpreter() *treeInterpreter {
|
||||
interpreter := treeInterpreter{}
|
||||
interpreter.fCall = newFunctionCaller()
|
||||
return &interpreter
|
||||
}
|
||||
|
||||
type expRef struct {
|
||||
ref ASTNode
|
||||
}
|
||||
|
||||
// Execute takes an ASTNode and input data and interprets the AST directly.
|
||||
// It will produce the result of applying the JMESPath expression associated
|
||||
// with the ASTNode to the input data "value".
|
||||
func (intr *treeInterpreter) Execute(node ASTNode, value interface{}) (interface{}, error) {
|
||||
switch node.nodeType {
|
||||
case ASTComparator:
|
||||
left, err := intr.Execute(node.children[0], value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
right, err := intr.Execute(node.children[1], value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch node.value {
|
||||
case tEQ:
|
||||
return objsEqual(left, right), nil
|
||||
case tNE:
|
||||
return !objsEqual(left, right), nil
|
||||
}
|
||||
leftNum, ok := left.(float64)
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
rightNum, ok := right.(float64)
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
switch node.value {
|
||||
case tGT:
|
||||
return leftNum > rightNum, nil
|
||||
case tGTE:
|
||||
return leftNum >= rightNum, nil
|
||||
case tLT:
|
||||
return leftNum < rightNum, nil
|
||||
case tLTE:
|
||||
return leftNum <= rightNum, nil
|
||||
}
|
||||
case ASTExpRef:
|
||||
return expRef{ref: node.children[0]}, nil
|
||||
case ASTFunctionExpression:
|
||||
resolvedArgs := []interface{}{}
|
||||
for _, arg := range node.children {
|
||||
current, err := intr.Execute(arg, value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resolvedArgs = append(resolvedArgs, current)
|
||||
}
|
||||
return intr.fCall.CallFunction(node.value.(string), resolvedArgs, intr)
|
||||
case ASTField:
|
||||
if m, ok := value.(map[string]interface{}); ok {
|
||||
key := node.value.(string)
|
||||
return m[key], nil
|
||||
}
|
||||
return intr.fieldFromStruct(node.value.(string), value)
|
||||
case ASTFilterProjection:
|
||||
left, err := intr.Execute(node.children[0], value)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
sliceType, ok := left.([]interface{})
|
||||
if !ok {
|
||||
if isSliceType(left) {
|
||||
return intr.filterProjectionWithReflection(node, left)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
compareNode := node.children[2]
|
||||
collected := []interface{}{}
|
||||
for _, element := range sliceType {
|
||||
result, err := intr.Execute(compareNode, element)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !isFalse(result) {
|
||||
current, err := intr.Execute(node.children[1], element)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if current != nil {
|
||||
collected = append(collected, current)
|
||||
}
|
||||
}
|
||||
}
|
||||
return collected, nil
|
||||
case ASTFlatten:
|
||||
left, err := intr.Execute(node.children[0], value)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
sliceType, ok := left.([]interface{})
|
||||
if !ok {
|
||||
// If we can't type convert to []interface{}, there's
|
||||
// a chance this could still work via reflection if we're
|
||||
// dealing with user provided types.
|
||||
if isSliceType(left) {
|
||||
return intr.flattenWithReflection(left)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
flattened := []interface{}{}
|
||||
for _, element := range sliceType {
|
||||
if elementSlice, ok := element.([]interface{}); ok {
|
||||
flattened = append(flattened, elementSlice...)
|
||||
} else if isSliceType(element) {
|
||||
reflectFlat := []interface{}{}
|
||||
v := reflect.ValueOf(element)
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
reflectFlat = append(reflectFlat, v.Index(i).Interface())
|
||||
}
|
||||
flattened = append(flattened, reflectFlat...)
|
||||
} else {
|
||||
flattened = append(flattened, element)
|
||||
}
|
||||
}
|
||||
return flattened, nil
|
||||
case ASTIdentity, ASTCurrentNode:
|
||||
return value, nil
|
||||
case ASTIndex:
|
||||
if sliceType, ok := value.([]interface{}); ok {
|
||||
index := node.value.(int)
|
||||
if index < 0 {
|
||||
index += len(sliceType)
|
||||
}
|
||||
if index < len(sliceType) && index >= 0 {
|
||||
return sliceType[index], nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
// Otherwise try via reflection.
|
||||
rv := reflect.ValueOf(value)
|
||||
if rv.Kind() == reflect.Slice {
|
||||
index := node.value.(int)
|
||||
if index < 0 {
|
||||
index += rv.Len()
|
||||
}
|
||||
if index < rv.Len() && index >= 0 {
|
||||
v := rv.Index(index)
|
||||
return v.Interface(), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
case ASTKeyValPair:
|
||||
return intr.Execute(node.children[0], value)
|
||||
case ASTLiteral:
|
||||
return node.value, nil
|
||||
case ASTMultiSelectHash:
|
||||
if value == nil {
|
||||
return nil, nil
|
||||
}
|
||||
collected := make(map[string]interface{})
|
||||
for _, child := range node.children {
|
||||
current, err := intr.Execute(child, value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key := child.value.(string)
|
||||
collected[key] = current
|
||||
}
|
||||
return collected, nil
|
||||
case ASTMultiSelectList:
|
||||
if value == nil {
|
||||
return nil, nil
|
||||
}
|
||||
collected := []interface{}{}
|
||||
for _, child := range node.children {
|
||||
current, err := intr.Execute(child, value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
collected = append(collected, current)
|
||||
}
|
||||
return collected, nil
|
||||
case ASTOrExpression:
|
||||
matched, err := intr.Execute(node.children[0], value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if isFalse(matched) {
|
||||
matched, err = intr.Execute(node.children[1], value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return matched, nil
|
||||
case ASTAndExpression:
|
||||
matched, err := intr.Execute(node.children[0], value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if isFalse(matched) {
|
||||
return matched, nil
|
||||
}
|
||||
return intr.Execute(node.children[1], value)
|
||||
case ASTNotExpression:
|
||||
matched, err := intr.Execute(node.children[0], value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if isFalse(matched) {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
case ASTPipe:
|
||||
result := value
|
||||
var err error
|
||||
for _, child := range node.children {
|
||||
result, err = intr.Execute(child, result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
case ASTProjection:
|
||||
left, err := intr.Execute(node.children[0], value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sliceType, ok := left.([]interface{})
|
||||
if !ok {
|
||||
if isSliceType(left) {
|
||||
return intr.projectWithReflection(node, left)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
collected := []interface{}{}
|
||||
var current interface{}
|
||||
for _, element := range sliceType {
|
||||
current, err = intr.Execute(node.children[1], element)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if current != nil {
|
||||
collected = append(collected, current)
|
||||
}
|
||||
}
|
||||
return collected, nil
|
||||
case ASTSubexpression, ASTIndexExpression:
|
||||
left, err := intr.Execute(node.children[0], value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return intr.Execute(node.children[1], left)
|
||||
case ASTSlice:
|
||||
sliceType, ok := value.([]interface{})
|
||||
if !ok {
|
||||
if isSliceType(value) {
|
||||
return intr.sliceWithReflection(node, value)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
parts := node.value.([]*int)
|
||||
sliceParams := make([]sliceParam, 3)
|
||||
for i, part := range parts {
|
||||
if part != nil {
|
||||
sliceParams[i].Specified = true
|
||||
sliceParams[i].N = *part
|
||||
}
|
||||
}
|
||||
return slice(sliceType, sliceParams)
|
||||
case ASTValueProjection:
|
||||
left, err := intr.Execute(node.children[0], value)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
mapType, ok := left.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
values := make([]interface{}, len(mapType))
|
||||
for _, value := range mapType {
|
||||
values = append(values, value)
|
||||
}
|
||||
collected := []interface{}{}
|
||||
for _, element := range values {
|
||||
current, err := intr.Execute(node.children[1], element)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if current != nil {
|
||||
collected = append(collected, current)
|
||||
}
|
||||
}
|
||||
return collected, nil
|
||||
}
|
||||
return nil, errors.New("Unknown AST node: " + node.nodeType.String())
|
||||
}
|
||||
|
||||
func (intr *treeInterpreter) fieldFromStruct(key string, value interface{}) (interface{}, error) {
|
||||
rv := reflect.ValueOf(value)
|
||||
first, n := utf8.DecodeRuneInString(key)
|
||||
fieldName := string(unicode.ToUpper(first)) + key[n:]
|
||||
if rv.Kind() == reflect.Struct {
|
||||
v := rv.FieldByName(fieldName)
|
||||
if !v.IsValid() {
|
||||
return nil, nil
|
||||
}
|
||||
return v.Interface(), nil
|
||||
} else if rv.Kind() == reflect.Ptr {
|
||||
// Handle multiple levels of indirection?
|
||||
if rv.IsNil() {
|
||||
return nil, nil
|
||||
}
|
||||
rv = rv.Elem()
|
||||
v := rv.FieldByName(fieldName)
|
||||
if !v.IsValid() {
|
||||
return nil, nil
|
||||
}
|
||||
return v.Interface(), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (intr *treeInterpreter) flattenWithReflection(value interface{}) (interface{}, error) {
|
||||
v := reflect.ValueOf(value)
|
||||
flattened := []interface{}{}
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
element := v.Index(i).Interface()
|
||||
if reflect.TypeOf(element).Kind() == reflect.Slice {
|
||||
// Then insert the contents of the element
|
||||
// slice into the flattened slice,
|
||||
// i.e flattened = append(flattened, mySlice...)
|
||||
elementV := reflect.ValueOf(element)
|
||||
for j := 0; j < elementV.Len(); j++ {
|
||||
flattened = append(
|
||||
flattened, elementV.Index(j).Interface())
|
||||
}
|
||||
} else {
|
||||
flattened = append(flattened, element)
|
||||
}
|
||||
}
|
||||
return flattened, nil
|
||||
}
|
||||
|
||||
func (intr *treeInterpreter) sliceWithReflection(node ASTNode, value interface{}) (interface{}, error) {
|
||||
v := reflect.ValueOf(value)
|
||||
parts := node.value.([]*int)
|
||||
sliceParams := make([]sliceParam, 3)
|
||||
for i, part := range parts {
|
||||
if part != nil {
|
||||
sliceParams[i].Specified = true
|
||||
sliceParams[i].N = *part
|
||||
}
|
||||
}
|
||||
final := []interface{}{}
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
element := v.Index(i).Interface()
|
||||
final = append(final, element)
|
||||
}
|
||||
return slice(final, sliceParams)
|
||||
}
|
||||
|
||||
func (intr *treeInterpreter) filterProjectionWithReflection(node ASTNode, value interface{}) (interface{}, error) {
|
||||
compareNode := node.children[2]
|
||||
collected := []interface{}{}
|
||||
v := reflect.ValueOf(value)
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
element := v.Index(i).Interface()
|
||||
result, err := intr.Execute(compareNode, element)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !isFalse(result) {
|
||||
current, err := intr.Execute(node.children[1], element)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if current != nil {
|
||||
collected = append(collected, current)
|
||||
}
|
||||
}
|
||||
}
|
||||
return collected, nil
|
||||
}
|
||||
|
||||
func (intr *treeInterpreter) projectWithReflection(node ASTNode, value interface{}) (interface{}, error) {
|
||||
collected := []interface{}{}
|
||||
v := reflect.ValueOf(value)
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
element := v.Index(i).Interface()
|
||||
result, err := intr.Execute(node.children[1], element)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if result != nil {
|
||||
collected = append(collected, result)
|
||||
}
|
||||
}
|
||||
return collected, nil
|
||||
}
|
420
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/lexer.go
generated
vendored
Normal file
420
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/lexer.go
generated
vendored
Normal file
@ -0,0 +1,420 @@
|
||||
package jmespath
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type token struct {
|
||||
tokenType tokType
|
||||
value string
|
||||
position int
|
||||
length int
|
||||
}
|
||||
|
||||
type tokType int
|
||||
|
||||
const eof = -1
|
||||
|
||||
// Lexer contains information about the expression being tokenized.
|
||||
type Lexer struct {
|
||||
expression string // The expression provided by the user.
|
||||
currentPos int // The current position in the string.
|
||||
lastWidth int // The width of the current rune. This
|
||||
buf bytes.Buffer // Internal buffer used for building up values.
|
||||
}
|
||||
|
||||
// SyntaxError is the main error used whenever a lexing or parsing error occurs.
|
||||
type SyntaxError struct {
|
||||
msg string // Error message displayed to user
|
||||
Expression string // Expression that generated a SyntaxError
|
||||
Offset int // The location in the string where the error occurred
|
||||
}
|
||||
|
||||
func (e SyntaxError) Error() string {
|
||||
// In the future, it would be good to underline the specific
|
||||
// location where the error occurred.
|
||||
return "SyntaxError: " + e.msg
|
||||
}
|
||||
|
||||
// HighlightLocation will show where the syntax error occurred.
|
||||
// It will place a "^" character on a line below the expression
|
||||
// at the point where the syntax error occurred.
|
||||
func (e SyntaxError) HighlightLocation() string {
|
||||
return e.Expression + "\n" + strings.Repeat(" ", e.Offset) + "^"
|
||||
}
|
||||
|
||||
//go:generate stringer -type=tokType
|
||||
const (
|
||||
tUnknown tokType = iota
|
||||
tStar
|
||||
tDot
|
||||
tFilter
|
||||
tFlatten
|
||||
tLparen
|
||||
tRparen
|
||||
tLbracket
|
||||
tRbracket
|
||||
tLbrace
|
||||
tRbrace
|
||||
tOr
|
||||
tPipe
|
||||
tNumber
|
||||
tUnquotedIdentifier
|
||||
tQuotedIdentifier
|
||||
tComma
|
||||
tColon
|
||||
tLT
|
||||
tLTE
|
||||
tGT
|
||||
tGTE
|
||||
tEQ
|
||||
tNE
|
||||
tJSONLiteral
|
||||
tStringLiteral
|
||||
tCurrent
|
||||
tExpref
|
||||
tAnd
|
||||
tNot
|
||||
tEOF
|
||||
)
|
||||
|
||||
var basicTokens = map[rune]tokType{
|
||||
'.': tDot,
|
||||
'*': tStar,
|
||||
',': tComma,
|
||||
':': tColon,
|
||||
'{': tLbrace,
|
||||
'}': tRbrace,
|
||||
']': tRbracket, // tLbracket not included because it could be "[]"
|
||||
'(': tLparen,
|
||||
')': tRparen,
|
||||
'@': tCurrent,
|
||||
}
|
||||
|
||||
// Bit mask for [a-zA-Z_] shifted down 64 bits to fit in a single uint64.
|
||||
// When using this bitmask just be sure to shift the rune down 64 bits
|
||||
// before checking against identifierStartBits.
|
||||
const identifierStartBits uint64 = 576460745995190270
|
||||
|
||||
// Bit mask for [a-zA-Z0-9], 128 bits -> 2 uint64s.
|
||||
var identifierTrailingBits = [2]uint64{287948901175001088, 576460745995190270}
|
||||
|
||||
var whiteSpace = map[rune]bool{
|
||||
' ': true, '\t': true, '\n': true, '\r': true,
|
||||
}
|
||||
|
||||
func (t token) String() string {
|
||||
return fmt.Sprintf("Token{%+v, %s, %d, %d}",
|
||||
t.tokenType, t.value, t.position, t.length)
|
||||
}
|
||||
|
||||
// NewLexer creates a new JMESPath lexer.
|
||||
func NewLexer() *Lexer {
|
||||
lexer := Lexer{}
|
||||
return &lexer
|
||||
}
|
||||
|
||||
func (lexer *Lexer) next() rune {
|
||||
if lexer.currentPos >= len(lexer.expression) {
|
||||
lexer.lastWidth = 0
|
||||
return eof
|
||||
}
|
||||
r, w := utf8.DecodeRuneInString(lexer.expression[lexer.currentPos:])
|
||||
lexer.lastWidth = w
|
||||
lexer.currentPos += w
|
||||
return r
|
||||
}
|
||||
|
||||
func (lexer *Lexer) back() {
|
||||
lexer.currentPos -= lexer.lastWidth
|
||||
}
|
||||
|
||||
func (lexer *Lexer) peek() rune {
|
||||
t := lexer.next()
|
||||
lexer.back()
|
||||
return t
|
||||
}
|
||||
|
||||
// tokenize takes an expression and returns corresponding tokens.
|
||||
func (lexer *Lexer) tokenize(expression string) ([]token, error) {
|
||||
var tokens []token
|
||||
lexer.expression = expression
|
||||
lexer.currentPos = 0
|
||||
lexer.lastWidth = 0
|
||||
loop:
|
||||
for {
|
||||
r := lexer.next()
|
||||
if identifierStartBits&(1<<(uint64(r)-64)) > 0 {
|
||||
t := lexer.consumeUnquotedIdentifier()
|
||||
tokens = append(tokens, t)
|
||||
} else if val, ok := basicTokens[r]; ok {
|
||||
// Basic single char token.
|
||||
t := token{
|
||||
tokenType: val,
|
||||
value: string(r),
|
||||
position: lexer.currentPos - lexer.lastWidth,
|
||||
length: 1,
|
||||
}
|
||||
tokens = append(tokens, t)
|
||||
} else if r == '-' || (r >= '0' && r <= '9') {
|
||||
t := lexer.consumeNumber()
|
||||
tokens = append(tokens, t)
|
||||
} else if r == '[' {
|
||||
t := lexer.consumeLBracket()
|
||||
tokens = append(tokens, t)
|
||||
} else if r == '"' {
|
||||
t, err := lexer.consumeQuotedIdentifier()
|
||||
if err != nil {
|
||||
return tokens, err
|
||||
}
|
||||
tokens = append(tokens, t)
|
||||
} else if r == '\'' {
|
||||
t, err := lexer.consumeRawStringLiteral()
|
||||
if err != nil {
|
||||
return tokens, err
|
||||
}
|
||||
tokens = append(tokens, t)
|
||||
} else if r == '`' {
|
||||
t, err := lexer.consumeLiteral()
|
||||
if err != nil {
|
||||
return tokens, err
|
||||
}
|
||||
tokens = append(tokens, t)
|
||||
} else if r == '|' {
|
||||
t := lexer.matchOrElse(r, '|', tOr, tPipe)
|
||||
tokens = append(tokens, t)
|
||||
} else if r == '<' {
|
||||
t := lexer.matchOrElse(r, '=', tLTE, tLT)
|
||||
tokens = append(tokens, t)
|
||||
} else if r == '>' {
|
||||
t := lexer.matchOrElse(r, '=', tGTE, tGT)
|
||||
tokens = append(tokens, t)
|
||||
} else if r == '!' {
|
||||
t := lexer.matchOrElse(r, '=', tNE, tNot)
|
||||
tokens = append(tokens, t)
|
||||
} else if r == '=' {
|
||||
t := lexer.matchOrElse(r, '=', tEQ, tUnknown)
|
||||
tokens = append(tokens, t)
|
||||
} else if r == '&' {
|
||||
t := lexer.matchOrElse(r, '&', tAnd, tExpref)
|
||||
tokens = append(tokens, t)
|
||||
} else if r == eof {
|
||||
break loop
|
||||
} else if _, ok := whiteSpace[r]; ok {
|
||||
// Ignore whitespace
|
||||
} else {
|
||||
return tokens, lexer.syntaxError(fmt.Sprintf("Unknown char: %s", strconv.QuoteRuneToASCII(r)))
|
||||
}
|
||||
}
|
||||
tokens = append(tokens, token{tEOF, "", len(lexer.expression), 0})
|
||||
return tokens, nil
|
||||
}
|
||||
|
||||
// Consume characters until the ending rune "r" is reached.
|
||||
// If the end of the expression is reached before seeing the
|
||||
// terminating rune "r", then an error is returned.
|
||||
// If no error occurs then the matching substring is returned.
|
||||
// The returned string will not include the ending rune.
|
||||
func (lexer *Lexer) consumeUntil(end rune) (string, error) {
|
||||
start := lexer.currentPos
|
||||
current := lexer.next()
|
||||
for current != end && current != eof {
|
||||
if current == '\\' && lexer.peek() != eof {
|
||||
lexer.next()
|
||||
}
|
||||
current = lexer.next()
|
||||
}
|
||||
if lexer.lastWidth == 0 {
|
||||
// Then we hit an EOF so we never reached the closing
|
||||
// delimiter.
|
||||
return "", SyntaxError{
|
||||
msg: "Unclosed delimiter: " + string(end),
|
||||
Expression: lexer.expression,
|
||||
Offset: len(lexer.expression),
|
||||
}
|
||||
}
|
||||
return lexer.expression[start : lexer.currentPos-lexer.lastWidth], nil
|
||||
}
|
||||
|
||||
func (lexer *Lexer) consumeLiteral() (token, error) {
|
||||
start := lexer.currentPos
|
||||
value, err := lexer.consumeUntil('`')
|
||||
if err != nil {
|
||||
return token{}, err
|
||||
}
|
||||
value = strings.Replace(value, "\\`", "`", -1)
|
||||
return token{
|
||||
tokenType: tJSONLiteral,
|
||||
value: value,
|
||||
position: start,
|
||||
length: len(value),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (lexer *Lexer) consumeRawStringLiteral() (token, error) {
|
||||
start := lexer.currentPos
|
||||
currentIndex := start
|
||||
current := lexer.next()
|
||||
for current != '\'' && lexer.peek() != eof {
|
||||
if current == '\\' && lexer.peek() == '\'' {
|
||||
chunk := lexer.expression[currentIndex : lexer.currentPos-1]
|
||||
lexer.buf.WriteString(chunk)
|
||||
lexer.buf.WriteString("'")
|
||||
lexer.next()
|
||||
currentIndex = lexer.currentPos
|
||||
}
|
||||
current = lexer.next()
|
||||
}
|
||||
if lexer.lastWidth == 0 {
|
||||
// Then we hit an EOF so we never reached the closing
|
||||
// delimiter.
|
||||
return token{}, SyntaxError{
|
||||
msg: "Unclosed delimiter: '",
|
||||
Expression: lexer.expression,
|
||||
Offset: len(lexer.expression),
|
||||
}
|
||||
}
|
||||
if currentIndex < lexer.currentPos {
|
||||
lexer.buf.WriteString(lexer.expression[currentIndex : lexer.currentPos-1])
|
||||
}
|
||||
value := lexer.buf.String()
|
||||
// Reset the buffer so it can reused again.
|
||||
lexer.buf.Reset()
|
||||
return token{
|
||||
tokenType: tStringLiteral,
|
||||
value: value,
|
||||
position: start,
|
||||
length: len(value),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (lexer *Lexer) syntaxError(msg string) SyntaxError {
|
||||
return SyntaxError{
|
||||
msg: msg,
|
||||
Expression: lexer.expression,
|
||||
Offset: lexer.currentPos - 1,
|
||||
}
|
||||
}
|
||||
|
||||
// Checks for a two char token, otherwise matches a single character
|
||||
// token. This is used whenever a two char token overlaps a single
|
||||
// char token, e.g. "||" -> tPipe, "|" -> tOr.
|
||||
func (lexer *Lexer) matchOrElse(first rune, second rune, matchedType tokType, singleCharType tokType) token {
|
||||
start := lexer.currentPos - lexer.lastWidth
|
||||
nextRune := lexer.next()
|
||||
var t token
|
||||
if nextRune == second {
|
||||
t = token{
|
||||
tokenType: matchedType,
|
||||
value: string(first) + string(second),
|
||||
position: start,
|
||||
length: 2,
|
||||
}
|
||||
} else {
|
||||
lexer.back()
|
||||
t = token{
|
||||
tokenType: singleCharType,
|
||||
value: string(first),
|
||||
position: start,
|
||||
length: 1,
|
||||
}
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func (lexer *Lexer) consumeLBracket() token {
|
||||
// There's three options here:
|
||||
// 1. A filter expression "[?"
|
||||
// 2. A flatten operator "[]"
|
||||
// 3. A bare rbracket "["
|
||||
start := lexer.currentPos - lexer.lastWidth
|
||||
nextRune := lexer.next()
|
||||
var t token
|
||||
if nextRune == '?' {
|
||||
t = token{
|
||||
tokenType: tFilter,
|
||||
value: "[?",
|
||||
position: start,
|
||||
length: 2,
|
||||
}
|
||||
} else if nextRune == ']' {
|
||||
t = token{
|
||||
tokenType: tFlatten,
|
||||
value: "[]",
|
||||
position: start,
|
||||
length: 2,
|
||||
}
|
||||
} else {
|
||||
t = token{
|
||||
tokenType: tLbracket,
|
||||
value: "[",
|
||||
position: start,
|
||||
length: 1,
|
||||
}
|
||||
lexer.back()
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func (lexer *Lexer) consumeQuotedIdentifier() (token, error) {
|
||||
start := lexer.currentPos
|
||||
value, err := lexer.consumeUntil('"')
|
||||
if err != nil {
|
||||
return token{}, err
|
||||
}
|
||||
var decoded string
|
||||
asJSON := []byte("\"" + value + "\"")
|
||||
if err := json.Unmarshal([]byte(asJSON), &decoded); err != nil {
|
||||
return token{}, err
|
||||
}
|
||||
return token{
|
||||
tokenType: tQuotedIdentifier,
|
||||
value: decoded,
|
||||
position: start - 1,
|
||||
length: len(decoded),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (lexer *Lexer) consumeUnquotedIdentifier() token {
|
||||
// Consume runes until we reach the end of an unquoted
|
||||
// identifier.
|
||||
start := lexer.currentPos - lexer.lastWidth
|
||||
for {
|
||||
r := lexer.next()
|
||||
if r < 0 || r > 128 || identifierTrailingBits[uint64(r)/64]&(1<<(uint64(r)%64)) == 0 {
|
||||
lexer.back()
|
||||
break
|
||||
}
|
||||
}
|
||||
value := lexer.expression[start:lexer.currentPos]
|
||||
return token{
|
||||
tokenType: tUnquotedIdentifier,
|
||||
value: value,
|
||||
position: start,
|
||||
length: lexer.currentPos - start,
|
||||
}
|
||||
}
|
||||
|
||||
func (lexer *Lexer) consumeNumber() token {
|
||||
// Consume runes until we reach something that's not a number.
|
||||
start := lexer.currentPos - lexer.lastWidth
|
||||
for {
|
||||
r := lexer.next()
|
||||
if r < '0' || r > '9' {
|
||||
lexer.back()
|
||||
break
|
||||
}
|
||||
}
|
||||
value := lexer.expression[start:lexer.currentPos]
|
||||
return token{
|
||||
tokenType: tNumber,
|
||||
value: value,
|
||||
position: start,
|
||||
length: lexer.currentPos - start,
|
||||
}
|
||||
}
|
603
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/parser.go
generated
vendored
Normal file
603
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/parser.go
generated
vendored
Normal file
@ -0,0 +1,603 @@
|
||||
package jmespath
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type astNodeType int
|
||||
|
||||
//go:generate stringer -type astNodeType
|
||||
const (
|
||||
ASTEmpty astNodeType = iota
|
||||
ASTComparator
|
||||
ASTCurrentNode
|
||||
ASTExpRef
|
||||
ASTFunctionExpression
|
||||
ASTField
|
||||
ASTFilterProjection
|
||||
ASTFlatten
|
||||
ASTIdentity
|
||||
ASTIndex
|
||||
ASTIndexExpression
|
||||
ASTKeyValPair
|
||||
ASTLiteral
|
||||
ASTMultiSelectHash
|
||||
ASTMultiSelectList
|
||||
ASTOrExpression
|
||||
ASTAndExpression
|
||||
ASTNotExpression
|
||||
ASTPipe
|
||||
ASTProjection
|
||||
ASTSubexpression
|
||||
ASTSlice
|
||||
ASTValueProjection
|
||||
)
|
||||
|
||||
// ASTNode represents the abstract syntax tree of a JMESPath expression.
|
||||
type ASTNode struct {
|
||||
nodeType astNodeType
|
||||
value interface{}
|
||||
children []ASTNode
|
||||
}
|
||||
|
||||
func (node ASTNode) String() string {
|
||||
return node.PrettyPrint(0)
|
||||
}
|
||||
|
||||
// PrettyPrint will pretty print the parsed AST.
|
||||
// The AST is an implementation detail and this pretty print
|
||||
// function is provided as a convenience method to help with
|
||||
// debugging. You should not rely on its output as the internal
|
||||
// structure of the AST may change at any time.
|
||||
func (node ASTNode) PrettyPrint(indent int) string {
|
||||
spaces := strings.Repeat(" ", indent)
|
||||
output := fmt.Sprintf("%s%s {\n", spaces, node.nodeType)
|
||||
nextIndent := indent + 2
|
||||
if node.value != nil {
|
||||
if converted, ok := node.value.(fmt.Stringer); ok {
|
||||
// Account for things like comparator nodes
|
||||
// that are enums with a String() method.
|
||||
output += fmt.Sprintf("%svalue: %s\n", strings.Repeat(" ", nextIndent), converted.String())
|
||||
} else {
|
||||
output += fmt.Sprintf("%svalue: %#v\n", strings.Repeat(" ", nextIndent), node.value)
|
||||
}
|
||||
}
|
||||
lastIndex := len(node.children)
|
||||
if lastIndex > 0 {
|
||||
output += fmt.Sprintf("%schildren: {\n", strings.Repeat(" ", nextIndent))
|
||||
childIndent := nextIndent + 2
|
||||
for _, elem := range node.children {
|
||||
output += elem.PrettyPrint(childIndent)
|
||||
}
|
||||
}
|
||||
output += fmt.Sprintf("%s}\n", spaces)
|
||||
return output
|
||||
}
|
||||
|
||||
var bindingPowers = map[tokType]int{
|
||||
tEOF: 0,
|
||||
tUnquotedIdentifier: 0,
|
||||
tQuotedIdentifier: 0,
|
||||
tRbracket: 0,
|
||||
tRparen: 0,
|
||||
tComma: 0,
|
||||
tRbrace: 0,
|
||||
tNumber: 0,
|
||||
tCurrent: 0,
|
||||
tExpref: 0,
|
||||
tColon: 0,
|
||||
tPipe: 1,
|
||||
tOr: 2,
|
||||
tAnd: 3,
|
||||
tEQ: 5,
|
||||
tLT: 5,
|
||||
tLTE: 5,
|
||||
tGT: 5,
|
||||
tGTE: 5,
|
||||
tNE: 5,
|
||||
tFlatten: 9,
|
||||
tStar: 20,
|
||||
tFilter: 21,
|
||||
tDot: 40,
|
||||
tNot: 45,
|
||||
tLbrace: 50,
|
||||
tLbracket: 55,
|
||||
tLparen: 60,
|
||||
}
|
||||
|
||||
// Parser holds state about the current expression being parsed.
|
||||
type Parser struct {
|
||||
expression string
|
||||
tokens []token
|
||||
index int
|
||||
}
|
||||
|
||||
// NewParser creates a new JMESPath parser.
|
||||
func NewParser() *Parser {
|
||||
p := Parser{}
|
||||
return &p
|
||||
}
|
||||
|
||||
// Parse will compile a JMESPath expression.
|
||||
func (p *Parser) Parse(expression string) (ASTNode, error) {
|
||||
lexer := NewLexer()
|
||||
p.expression = expression
|
||||
p.index = 0
|
||||
tokens, err := lexer.tokenize(expression)
|
||||
if err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
p.tokens = tokens
|
||||
parsed, err := p.parseExpression(0)
|
||||
if err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
if p.current() != tEOF {
|
||||
return ASTNode{}, p.syntaxError(fmt.Sprintf(
|
||||
"Unexpected token at the end of the expresssion: %s", p.current()))
|
||||
}
|
||||
return parsed, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseExpression(bindingPower int) (ASTNode, error) {
|
||||
var err error
|
||||
leftToken := p.lookaheadToken(0)
|
||||
p.advance()
|
||||
leftNode, err := p.nud(leftToken)
|
||||
if err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
currentToken := p.current()
|
||||
for bindingPower < bindingPowers[currentToken] {
|
||||
p.advance()
|
||||
leftNode, err = p.led(currentToken, leftNode)
|
||||
if err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
currentToken = p.current()
|
||||
}
|
||||
return leftNode, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseIndexExpression() (ASTNode, error) {
|
||||
if p.lookahead(0) == tColon || p.lookahead(1) == tColon {
|
||||
return p.parseSliceExpression()
|
||||
}
|
||||
indexStr := p.lookaheadToken(0).value
|
||||
parsedInt, err := strconv.Atoi(indexStr)
|
||||
if err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
indexNode := ASTNode{nodeType: ASTIndex, value: parsedInt}
|
||||
p.advance()
|
||||
if err := p.match(tRbracket); err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
return indexNode, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseSliceExpression() (ASTNode, error) {
|
||||
parts := []*int{nil, nil, nil}
|
||||
index := 0
|
||||
current := p.current()
|
||||
for current != tRbracket && index < 3 {
|
||||
if current == tColon {
|
||||
index++
|
||||
p.advance()
|
||||
} else if current == tNumber {
|
||||
parsedInt, err := strconv.Atoi(p.lookaheadToken(0).value)
|
||||
if err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
parts[index] = &parsedInt
|
||||
p.advance()
|
||||
} else {
|
||||
return ASTNode{}, p.syntaxError(
|
||||
"Expected tColon or tNumber" + ", received: " + p.current().String())
|
||||
}
|
||||
current = p.current()
|
||||
}
|
||||
if err := p.match(tRbracket); err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
return ASTNode{
|
||||
nodeType: ASTSlice,
|
||||
value: parts,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *Parser) match(tokenType tokType) error {
|
||||
if p.current() == tokenType {
|
||||
p.advance()
|
||||
return nil
|
||||
}
|
||||
return p.syntaxError("Expected " + tokenType.String() + ", received: " + p.current().String())
|
||||
}
|
||||
|
||||
func (p *Parser) led(tokenType tokType, node ASTNode) (ASTNode, error) {
|
||||
switch tokenType {
|
||||
case tDot:
|
||||
if p.current() != tStar {
|
||||
right, err := p.parseDotRHS(bindingPowers[tDot])
|
||||
return ASTNode{
|
||||
nodeType: ASTSubexpression,
|
||||
children: []ASTNode{node, right},
|
||||
}, err
|
||||
}
|
||||
p.advance()
|
||||
right, err := p.parseProjectionRHS(bindingPowers[tDot])
|
||||
return ASTNode{
|
||||
nodeType: ASTValueProjection,
|
||||
children: []ASTNode{node, right},
|
||||
}, err
|
||||
case tPipe:
|
||||
right, err := p.parseExpression(bindingPowers[tPipe])
|
||||
return ASTNode{nodeType: ASTPipe, children: []ASTNode{node, right}}, err
|
||||
case tOr:
|
||||
right, err := p.parseExpression(bindingPowers[tOr])
|
||||
return ASTNode{nodeType: ASTOrExpression, children: []ASTNode{node, right}}, err
|
||||
case tAnd:
|
||||
right, err := p.parseExpression(bindingPowers[tAnd])
|
||||
return ASTNode{nodeType: ASTAndExpression, children: []ASTNode{node, right}}, err
|
||||
case tLparen:
|
||||
name := node.value
|
||||
var args []ASTNode
|
||||
for p.current() != tRparen {
|
||||
expression, err := p.parseExpression(0)
|
||||
if err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
if p.current() == tComma {
|
||||
if err := p.match(tComma); err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
}
|
||||
args = append(args, expression)
|
||||
}
|
||||
if err := p.match(tRparen); err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
return ASTNode{
|
||||
nodeType: ASTFunctionExpression,
|
||||
value: name,
|
||||
children: args,
|
||||
}, nil
|
||||
case tFilter:
|
||||
return p.parseFilter(node)
|
||||
case tFlatten:
|
||||
left := ASTNode{nodeType: ASTFlatten, children: []ASTNode{node}}
|
||||
right, err := p.parseProjectionRHS(bindingPowers[tFlatten])
|
||||
return ASTNode{
|
||||
nodeType: ASTProjection,
|
||||
children: []ASTNode{left, right},
|
||||
}, err
|
||||
case tEQ, tNE, tGT, tGTE, tLT, tLTE:
|
||||
right, err := p.parseExpression(bindingPowers[tokenType])
|
||||
if err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
return ASTNode{
|
||||
nodeType: ASTComparator,
|
||||
value: tokenType,
|
||||
children: []ASTNode{node, right},
|
||||
}, nil
|
||||
case tLbracket:
|
||||
tokenType := p.current()
|
||||
var right ASTNode
|
||||
var err error
|
||||
if tokenType == tNumber || tokenType == tColon {
|
||||
right, err = p.parseIndexExpression()
|
||||
if err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
return p.projectIfSlice(node, right)
|
||||
}
|
||||
// Otherwise this is a projection.
|
||||
if err := p.match(tStar); err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
if err := p.match(tRbracket); err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
right, err = p.parseProjectionRHS(bindingPowers[tStar])
|
||||
if err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
return ASTNode{
|
||||
nodeType: ASTProjection,
|
||||
children: []ASTNode{node, right},
|
||||
}, nil
|
||||
}
|
||||
return ASTNode{}, p.syntaxError("Unexpected token: " + tokenType.String())
|
||||
}
|
||||
|
||||
func (p *Parser) nud(token token) (ASTNode, error) {
|
||||
switch token.tokenType {
|
||||
case tJSONLiteral:
|
||||
var parsed interface{}
|
||||
err := json.Unmarshal([]byte(token.value), &parsed)
|
||||
if err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
return ASTNode{nodeType: ASTLiteral, value: parsed}, nil
|
||||
case tStringLiteral:
|
||||
return ASTNode{nodeType: ASTLiteral, value: token.value}, nil
|
||||
case tUnquotedIdentifier:
|
||||
return ASTNode{
|
||||
nodeType: ASTField,
|
||||
value: token.value,
|
||||
}, nil
|
||||
case tQuotedIdentifier:
|
||||
node := ASTNode{nodeType: ASTField, value: token.value}
|
||||
if p.current() == tLparen {
|
||||
return ASTNode{}, p.syntaxErrorToken("Can't have quoted identifier as function name.", token)
|
||||
}
|
||||
return node, nil
|
||||
case tStar:
|
||||
left := ASTNode{nodeType: ASTIdentity}
|
||||
var right ASTNode
|
||||
var err error
|
||||
if p.current() == tRbracket {
|
||||
right = ASTNode{nodeType: ASTIdentity}
|
||||
} else {
|
||||
right, err = p.parseProjectionRHS(bindingPowers[tStar])
|
||||
}
|
||||
return ASTNode{nodeType: ASTValueProjection, children: []ASTNode{left, right}}, err
|
||||
case tFilter:
|
||||
return p.parseFilter(ASTNode{nodeType: ASTIdentity})
|
||||
case tLbrace:
|
||||
return p.parseMultiSelectHash()
|
||||
case tFlatten:
|
||||
left := ASTNode{
|
||||
nodeType: ASTFlatten,
|
||||
children: []ASTNode{ASTNode{nodeType: ASTIdentity}},
|
||||
}
|
||||
right, err := p.parseProjectionRHS(bindingPowers[tFlatten])
|
||||
if err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
return ASTNode{nodeType: ASTProjection, children: []ASTNode{left, right}}, nil
|
||||
case tLbracket:
|
||||
tokenType := p.current()
|
||||
//var right ASTNode
|
||||
if tokenType == tNumber || tokenType == tColon {
|
||||
right, err := p.parseIndexExpression()
|
||||
if err != nil {
|
||||
return ASTNode{}, nil
|
||||
}
|
||||
return p.projectIfSlice(ASTNode{nodeType: ASTIdentity}, right)
|
||||
} else if tokenType == tStar && p.lookahead(1) == tRbracket {
|
||||
p.advance()
|
||||
p.advance()
|
||||
right, err := p.parseProjectionRHS(bindingPowers[tStar])
|
||||
if err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
return ASTNode{
|
||||
nodeType: ASTProjection,
|
||||
children: []ASTNode{ASTNode{nodeType: ASTIdentity}, right},
|
||||
}, nil
|
||||
} else {
|
||||
return p.parseMultiSelectList()
|
||||
}
|
||||
case tCurrent:
|
||||
return ASTNode{nodeType: ASTCurrentNode}, nil
|
||||
case tExpref:
|
||||
expression, err := p.parseExpression(bindingPowers[tExpref])
|
||||
if err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
return ASTNode{nodeType: ASTExpRef, children: []ASTNode{expression}}, nil
|
||||
case tNot:
|
||||
expression, err := p.parseExpression(bindingPowers[tNot])
|
||||
if err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
return ASTNode{nodeType: ASTNotExpression, children: []ASTNode{expression}}, nil
|
||||
case tLparen:
|
||||
expression, err := p.parseExpression(0)
|
||||
if err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
if err := p.match(tRparen); err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
return expression, nil
|
||||
case tEOF:
|
||||
return ASTNode{}, p.syntaxErrorToken("Incomplete expression", token)
|
||||
}
|
||||
|
||||
return ASTNode{}, p.syntaxErrorToken("Invalid token: "+token.tokenType.String(), token)
|
||||
}
|
||||
|
||||
func (p *Parser) parseMultiSelectList() (ASTNode, error) {
|
||||
var expressions []ASTNode
|
||||
for {
|
||||
expression, err := p.parseExpression(0)
|
||||
if err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
expressions = append(expressions, expression)
|
||||
if p.current() == tRbracket {
|
||||
break
|
||||
}
|
||||
err = p.match(tComma)
|
||||
if err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
}
|
||||
err := p.match(tRbracket)
|
||||
if err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
return ASTNode{
|
||||
nodeType: ASTMultiSelectList,
|
||||
children: expressions,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseMultiSelectHash() (ASTNode, error) {
|
||||
var children []ASTNode
|
||||
for {
|
||||
keyToken := p.lookaheadToken(0)
|
||||
if err := p.match(tUnquotedIdentifier); err != nil {
|
||||
if err := p.match(tQuotedIdentifier); err != nil {
|
||||
return ASTNode{}, p.syntaxError("Expected tQuotedIdentifier or tUnquotedIdentifier")
|
||||
}
|
||||
}
|
||||
keyName := keyToken.value
|
||||
err := p.match(tColon)
|
||||
if err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
value, err := p.parseExpression(0)
|
||||
if err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
node := ASTNode{
|
||||
nodeType: ASTKeyValPair,
|
||||
value: keyName,
|
||||
children: []ASTNode{value},
|
||||
}
|
||||
children = append(children, node)
|
||||
if p.current() == tComma {
|
||||
err := p.match(tComma)
|
||||
if err != nil {
|
||||
return ASTNode{}, nil
|
||||
}
|
||||
} else if p.current() == tRbrace {
|
||||
err := p.match(tRbrace)
|
||||
if err != nil {
|
||||
return ASTNode{}, nil
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return ASTNode{
|
||||
nodeType: ASTMultiSelectHash,
|
||||
children: children,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *Parser) projectIfSlice(left ASTNode, right ASTNode) (ASTNode, error) {
|
||||
indexExpr := ASTNode{
|
||||
nodeType: ASTIndexExpression,
|
||||
children: []ASTNode{left, right},
|
||||
}
|
||||
if right.nodeType == ASTSlice {
|
||||
right, err := p.parseProjectionRHS(bindingPowers[tStar])
|
||||
return ASTNode{
|
||||
nodeType: ASTProjection,
|
||||
children: []ASTNode{indexExpr, right},
|
||||
}, err
|
||||
}
|
||||
return indexExpr, nil
|
||||
}
|
||||
func (p *Parser) parseFilter(node ASTNode) (ASTNode, error) {
|
||||
var right, condition ASTNode
|
||||
var err error
|
||||
condition, err = p.parseExpression(0)
|
||||
if err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
if err := p.match(tRbracket); err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
if p.current() == tFlatten {
|
||||
right = ASTNode{nodeType: ASTIdentity}
|
||||
} else {
|
||||
right, err = p.parseProjectionRHS(bindingPowers[tFilter])
|
||||
if err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
}
|
||||
|
||||
return ASTNode{
|
||||
nodeType: ASTFilterProjection,
|
||||
children: []ASTNode{node, right, condition},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseDotRHS(bindingPower int) (ASTNode, error) {
|
||||
lookahead := p.current()
|
||||
if tokensOneOf([]tokType{tQuotedIdentifier, tUnquotedIdentifier, tStar}, lookahead) {
|
||||
return p.parseExpression(bindingPower)
|
||||
} else if lookahead == tLbracket {
|
||||
if err := p.match(tLbracket); err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
return p.parseMultiSelectList()
|
||||
} else if lookahead == tLbrace {
|
||||
if err := p.match(tLbrace); err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
return p.parseMultiSelectHash()
|
||||
}
|
||||
return ASTNode{}, p.syntaxError("Expected identifier, lbracket, or lbrace")
|
||||
}
|
||||
|
||||
func (p *Parser) parseProjectionRHS(bindingPower int) (ASTNode, error) {
|
||||
current := p.current()
|
||||
if bindingPowers[current] < 10 {
|
||||
return ASTNode{nodeType: ASTIdentity}, nil
|
||||
} else if current == tLbracket {
|
||||
return p.parseExpression(bindingPower)
|
||||
} else if current == tFilter {
|
||||
return p.parseExpression(bindingPower)
|
||||
} else if current == tDot {
|
||||
err := p.match(tDot)
|
||||
if err != nil {
|
||||
return ASTNode{}, err
|
||||
}
|
||||
return p.parseDotRHS(bindingPower)
|
||||
} else {
|
||||
return ASTNode{}, p.syntaxError("Error")
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) lookahead(number int) tokType {
|
||||
return p.lookaheadToken(number).tokenType
|
||||
}
|
||||
|
||||
func (p *Parser) current() tokType {
|
||||
return p.lookahead(0)
|
||||
}
|
||||
|
||||
func (p *Parser) lookaheadToken(number int) token {
|
||||
return p.tokens[p.index+number]
|
||||
}
|
||||
|
||||
func (p *Parser) advance() {
|
||||
p.index++
|
||||
}
|
||||
|
||||
func tokensOneOf(elements []tokType, token tokType) bool {
|
||||
for _, elem := range elements {
|
||||
if elem == token {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Parser) syntaxError(msg string) SyntaxError {
|
||||
return SyntaxError{
|
||||
msg: msg,
|
||||
Expression: p.expression,
|
||||
Offset: p.lookaheadToken(0).position,
|
||||
}
|
||||
}
|
||||
|
||||
// Create a SyntaxError based on the provided token.
|
||||
// This differs from syntaxError() which creates a SyntaxError
|
||||
// based on the current lookahead token.
|
||||
func (p *Parser) syntaxErrorToken(msg string, t token) SyntaxError {
|
||||
return SyntaxError{
|
||||
msg: msg,
|
||||
Expression: p.expression,
|
||||
Offset: t.position,
|
||||
}
|
||||
}
|
16
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/toktype_string.go
generated
vendored
Normal file
16
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/toktype_string.go
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
// generated by stringer -type=tokType; DO NOT EDIT
|
||||
|
||||
package jmespath
|
||||
|
||||
import "fmt"
|
||||
|
||||
const _tokType_name = "tUnknowntStartDottFiltertFlattentLparentRparentLbrackettRbrackettLbracetRbracetOrtPipetNumbertUnquotedIdentifiertQuotedIdentifiertCommatColontLTtLTEtGTtGTEtEQtNEtJSONLiteraltStringLiteraltCurrenttExpreftAndtNottEOF"
|
||||
|
||||
var _tokType_index = [...]uint8{0, 8, 13, 17, 24, 32, 39, 46, 55, 64, 71, 78, 81, 86, 93, 112, 129, 135, 141, 144, 148, 151, 155, 158, 161, 173, 187, 195, 202, 206, 210, 214}
|
||||
|
||||
func (i tokType) String() string {
|
||||
if i < 0 || i >= tokType(len(_tokType_index)-1) {
|
||||
return fmt.Sprintf("tokType(%d)", i)
|
||||
}
|
||||
return _tokType_name[_tokType_index[i]:_tokType_index[i+1]]
|
||||
}
|
185
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/util.go
generated
vendored
Normal file
185
vendor/github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath/util.go
generated
vendored
Normal file
@ -0,0 +1,185 @@
|
||||
package jmespath
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// IsFalse determines if an object is false based on the JMESPath spec.
|
||||
// JMESPath defines false values to be any of:
|
||||
// - An empty string array, or hash.
|
||||
// - The boolean value false.
|
||||
// - nil
|
||||
func isFalse(value interface{}) bool {
|
||||
switch v := value.(type) {
|
||||
case bool:
|
||||
return !v
|
||||
case []interface{}:
|
||||
return len(v) == 0
|
||||
case map[string]interface{}:
|
||||
return len(v) == 0
|
||||
case string:
|
||||
return len(v) == 0
|
||||
case nil:
|
||||
return true
|
||||
}
|
||||
// Try the reflection cases before returning false.
|
||||
rv := reflect.ValueOf(value)
|
||||
switch rv.Kind() {
|
||||
case reflect.Struct:
|
||||
// A struct type will never be false, even if
|
||||
// all of its values are the zero type.
|
||||
return false
|
||||
case reflect.Slice, reflect.Map:
|
||||
return rv.Len() == 0
|
||||
case reflect.Ptr:
|
||||
if rv.IsNil() {
|
||||
return true
|
||||
}
|
||||
// If it's a pointer type, we'll try to deref the pointer
|
||||
// and evaluate the pointer value for isFalse.
|
||||
element := rv.Elem()
|
||||
return isFalse(element.Interface())
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ObjsEqual is a generic object equality check.
|
||||
// It will take two arbitrary objects and recursively determine
|
||||
// if they are equal.
|
||||
func objsEqual(left interface{}, right interface{}) bool {
|
||||
return reflect.DeepEqual(left, right)
|
||||
}
|
||||
|
||||
// SliceParam refers to a single part of a slice.
|
||||
// A slice consists of a start, a stop, and a step, similar to
|
||||
// python slices.
|
||||
type sliceParam struct {
|
||||
N int
|
||||
Specified bool
|
||||
}
|
||||
|
||||
// Slice supports [start:stop:step] style slicing that's supported in JMESPath.
|
||||
func slice(slice []interface{}, parts []sliceParam) ([]interface{}, error) {
|
||||
computed, err := computeSliceParams(len(slice), parts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
start, stop, step := computed[0], computed[1], computed[2]
|
||||
result := []interface{}{}
|
||||
if step > 0 {
|
||||
for i := start; i < stop; i += step {
|
||||
result = append(result, slice[i])
|
||||
}
|
||||
} else {
|
||||
for i := start; i > stop; i += step {
|
||||
result = append(result, slice[i])
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func computeSliceParams(length int, parts []sliceParam) ([]int, error) {
|
||||
var start, stop, step int
|
||||
if !parts[2].Specified {
|
||||
step = 1
|
||||
} else if parts[2].N == 0 {
|
||||
return nil, errors.New("Invalid slice, step cannot be 0")
|
||||
} else {
|
||||
step = parts[2].N
|
||||
}
|
||||
var stepValueNegative bool
|
||||
if step < 0 {
|
||||
stepValueNegative = true
|
||||
} else {
|
||||
stepValueNegative = false
|
||||
}
|
||||
|
||||
if !parts[0].Specified {
|
||||
if stepValueNegative {
|
||||
start = length - 1
|
||||
} else {
|
||||
start = 0
|
||||
}
|
||||
} else {
|
||||
start = capSlice(length, parts[0].N, step)
|
||||
}
|
||||
|
||||
if !parts[1].Specified {
|
||||
if stepValueNegative {
|
||||
stop = -1
|
||||
} else {
|
||||
stop = length
|
||||
}
|
||||
} else {
|
||||
stop = capSlice(length, parts[1].N, step)
|
||||
}
|
||||
return []int{start, stop, step}, nil
|
||||
}
|
||||
|
||||
func capSlice(length int, actual int, step int) int {
|
||||
if actual < 0 {
|
||||
actual += length
|
||||
if actual < 0 {
|
||||
if step < 0 {
|
||||
actual = -1
|
||||
} else {
|
||||
actual = 0
|
||||
}
|
||||
}
|
||||
} else if actual >= length {
|
||||
if step < 0 {
|
||||
actual = length - 1
|
||||
} else {
|
||||
actual = length
|
||||
}
|
||||
}
|
||||
return actual
|
||||
}
|
||||
|
||||
// ToArrayNum converts an empty interface type to a slice of float64.
|
||||
// If any element in the array cannot be converted, then nil is returned
|
||||
// along with a second value of false.
|
||||
func toArrayNum(data interface{}) ([]float64, bool) {
|
||||
// Is there a better way to do this with reflect?
|
||||
if d, ok := data.([]interface{}); ok {
|
||||
result := make([]float64, len(d))
|
||||
for i, el := range d {
|
||||
item, ok := el.(float64)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
result[i] = item
|
||||
}
|
||||
return result, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// ToArrayStr converts an empty interface type to a slice of strings.
|
||||
// If any element in the array cannot be converted, then nil is returned
|
||||
// along with a second value of false. If the input data could be entirely
|
||||
// converted, then the converted data, along with a second value of true,
|
||||
// will be returned.
|
||||
func toArrayStr(data interface{}) ([]string, bool) {
|
||||
// Is there a better way to do this with reflect?
|
||||
if d, ok := data.([]interface{}); ok {
|
||||
result := make([]string, len(d))
|
||||
for i, el := range d {
|
||||
item, ok := el.(string)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
result[i] = item
|
||||
}
|
||||
return result, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func isSliceType(v interface{}) bool {
|
||||
if v == nil {
|
||||
return false
|
||||
}
|
||||
return reflect.TypeOf(v).Kind() == reflect.Slice
|
||||
}
|
Loading…
Reference in New Issue
Block a user