func CidrSubnet(prefix, newbits, netnum cty.Value) (cty.Value, error) {
	return CidrSubnetFunc.Call([]cty.Value{prefix, newbits, netnum})
}
CidrSubnet calculates a subnet address within a given IP network address prefix.
package funcs
import (
	"fmt"
	"net"
	"github.com/apparentlymart/go-cidr/cidr"
	"github.com/zclconf/go-cty/cty"
	"github.com/zclconf/go-cty/cty/function"
	"github.com/zclconf/go-cty/cty/gocty"
)
var CidrHostFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "prefix",
			Type: cty.String,
		},
		{
			Name: "hostnum",
			Type: cty.Number,
		},
	},
	Type: function.StaticReturnType(cty.String),
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		var hostNum int
		if err := gocty.FromCtyValue(args[1], &hostNum); err != nil {
			return cty.UnknownVal(cty.String), err
		}
		_, network, err := net.ParseCIDR(args[0].AsString())
		if err != nil {
			return cty.UnknownVal(cty.String), fmt.Errorf("invalid CIDR expression: %s", err)
		}
		ip, err := cidr.Host(network, hostNum)
		if err != nil {
			return cty.UnknownVal(cty.String), err
		}
		return cty.StringVal(ip.String()), nil
	},
})
var CidrNetmaskFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "prefix",
			Type: cty.String,
		},
	},
	Type: function.StaticReturnType(cty.String),
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		_, network, err := net.ParseCIDR(args[0].AsString())
		if err != nil {
			return cty.UnknownVal(cty.String), fmt.Errorf("invalid CIDR expression: %s", err)
		}
		return cty.StringVal(net.IP(network.Mask).String()), nil
	},
})
var CidrSubnetFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "prefix",
			Type: cty.String,
		},
		{
			Name: "newbits",
			Type: cty.Number,
		},
		{
			Name: "netnum",
			Type: cty.Number,
		},
	},
	Type: function.StaticReturnType(cty.String),
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		var newbits int
		if err := gocty.FromCtyValue(args[1], &newbits); err != nil {
			return cty.UnknownVal(cty.String), err
		}
		var netnum int
		if err := gocty.FromCtyValue(args[2], &netnum); err != nil {
			return cty.UnknownVal(cty.String), err
		}
		_, network, err := net.ParseCIDR(args[0].AsString())
		if err != nil {
			return cty.UnknownVal(cty.String), fmt.Errorf("invalid CIDR expression: %s", err)
		}
		if newbits > 32 {
			return cty.UnknownVal(cty.String), fmt.Errorf("may not extend prefix by more than 32 bits")
		}
		newNetwork, err := cidr.Subnet(network, newbits, netnum)
		if err != nil {
			return cty.UnknownVal(cty.String), err
		}
		return cty.StringVal(newNetwork.String()), nil
	},
})
var CidrSubnetsFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "prefix",
			Type: cty.String,
		},
	},
	VarParam: &function.Parameter{
		Name: "newbits",
		Type: cty.Number,
	},
	Type: function.StaticReturnType(cty.List(cty.String)),
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		_, network, err := net.ParseCIDR(args[0].AsString())
		if err != nil {
			return cty.UnknownVal(cty.String), function.NewArgErrorf(0, "invalid CIDR expression: %s", err)
		}
		startPrefixLen, _ := network.Mask.Size()
		prefixLengthArgs := args[1:]
		if len(prefixLengthArgs) == 0 {
			return cty.ListValEmpty(cty.String), nil
		}
		var firstLength int
		if err := gocty.FromCtyValue(prefixLengthArgs[0], &firstLength); err != nil {
			return cty.UnknownVal(cty.String), function.NewArgError(1, err)
		}
		firstLength += startPrefixLen
		retVals := make([]cty.Value, len(prefixLengthArgs))
		current, _ := cidr.PreviousSubnet(network, firstLength)
		for i, lengthArg := range prefixLengthArgs {
			var length int
			if err := gocty.FromCtyValue(lengthArg, &length); err != nil {
				return cty.UnknownVal(cty.String), function.NewArgError(i+1, err)
			}
			if length < 1 {
				return cty.UnknownVal(cty.String), function.NewArgErrorf(i+1, "must extend prefix by at least one bit")
			}
			if length > 32 {
				return cty.UnknownVal(cty.String), function.NewArgErrorf(i+1, "may not extend prefix by more than 32 bits")
			}
			length += startPrefixLen
			if length > (len(network.IP) * 8) {
				protocol := "IP"
				switch len(network.IP) * 8 {
				case 32:
					protocol = "IPv4"
				case 128:
					protocol = "IPv6"
				}
				return cty.UnknownVal(cty.String), function.NewArgErrorf(i+1, "would extend prefix to %d bits, which is too long for an %s address", length, protocol)
			}
			next, rollover := cidr.NextSubnet(current, length)
			if rollover || !network.Contains(next.IP) {
				return cty.UnknownVal(cty.String), function.NewArgErrorf(i+1, "not enough remaining address space for a subnet with a prefix of %d bits after %s", length, current.String())
			}
			current = next
			retVals[i] = cty.StringVal(current.String())
		}
		return cty.ListVal(retVals), nil
	},
})
func CidrHost(prefix, hostnum cty.Value) (cty.Value, error) {
	return CidrHostFunc.Call([]cty.Value{prefix, hostnum})
}
func CidrNetmask(prefix cty.Value) (cty.Value, error) {
	return CidrNetmaskFunc.Call([]cty.Value{prefix})
}