pkg/net: added package
Support:
- various IP types
- FQDNs
Also supports:
- use of single-param builtins as types
(consistent with curried builtins).
- fixed bug in interpretation of top
- allow unexported functions to be used by builtins
Change-Id: I3568f2383510a904e00d4cf941c753efd03679ce
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/2664
Reviewed-by: Marcel van Lohuizen <mpvl@google.com>
diff --git a/pkg/net/host.go b/pkg/net/host.go
new file mode 100644
index 0000000..a690fac
--- /dev/null
+++ b/pkg/net/host.go
@@ -0,0 +1,105 @@
+// Copyright 2019 CUE Authors
+//
+// 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 net
+
+import (
+ "fmt"
+ "net"
+ "strconv"
+ "unicode/utf8"
+
+ "cuelang.org/go/cue"
+ "golang.org/x/net/idna"
+)
+
+var idnaProfile = idna.New(
+ idna.ValidateLabels(true),
+ idna.VerifyDNSLength(true),
+ idna.StrictDomainName(true),
+)
+
+// SplitHostPort splits a network address of the form "host:port",
+// "host%zone:port", "[host]:port" or "[host%zone]:port" into host or host%zone
+// and port.
+//
+// A literal IPv6 address in hostport must be enclosed in square brackets, as in
+// "[::1]:80", "[::1%lo0]:80".
+func SplitHostPort(s string) (hostport []string, err error) {
+ host, port, err := net.SplitHostPort(s)
+ if err != nil {
+ return nil, err
+ }
+ return []string{host, port}, nil
+}
+
+// JoinHostPort combines host and port into a network address of the
+// form "host:port". If host contains a colon, as found in literal
+// IPv6 addresses, then JoinHostPort returns "[host]:port".
+//
+// See func Dial for a description of the host and port parameters.
+func JoinHostPort(host, port cue.Value) (string, error) {
+ var err error
+ hostStr := ""
+ switch host.Kind() {
+ case cue.ListKind:
+ ipdata := netGetIP(host)
+ if len(ipdata) != 4 && len(ipdata) != 16 {
+ err = fmt.Errorf("invalid host %q", host)
+ }
+ hostStr = ipdata.String()
+ case cue.BytesKind:
+ var b []byte
+ b, err = host.Bytes()
+ hostStr = string(b)
+ default:
+ hostStr, err = host.String()
+ }
+ if err != nil {
+ return "", err
+ }
+
+ portStr := ""
+ switch port.Kind() {
+ case cue.StringKind:
+ portStr, err = port.String()
+ case cue.BytesKind:
+ var b []byte
+ b, err = port.Bytes()
+ portStr = string(b)
+ default:
+ var i int64
+ i, err = port.Int64()
+ portStr = strconv.Itoa(int(i))
+ }
+ if err != nil {
+ return "", err
+ }
+
+ return net.JoinHostPort(hostStr, portStr), nil
+}
+
+// FQDN reports whether is is a valid fully qualified domain name.
+//
+// FQDN allows only ASCII characters as prescribed by RFC 1034 (A-Z, a-z, 0-9
+// and the hyphen).
+func FQDN(s string) bool {
+ for i := 0; i < len(s); i++ {
+ if s[i] >= utf8.RuneSelf {
+ return false
+ }
+ }
+ _, err := idnaProfile.ToASCII(s)
+ return err == nil
+}