blob: 8f941f1adbda1eea74da42ee96c38fe3b5cc62f6 [file] [log] [blame]
David K. Bainbridge528b3182017-01-23 08:51:59 -08001// Copyright 2012-2016 Canonical Ltd.
2// Licensed under the LGPLv3, see LICENCE file for details.
3
4package gomaasapi
5
6import (
7 "bytes"
8 "encoding/binary"
9 "encoding/json"
10 "errors"
11 "net"
12 "net/http"
13 "strconv"
14)
15
16// NameOrIDToID takes a string that contains eiter an integer ID or the
17// name of a thing. It returns the integer ID contained or mapped to or panics.
18func NameOrIDToID(v string, nameToID map[string]uint, minID, maxID uint) (ID uint, err error) {
19 ID, ok := nameToID[v]
20 if !ok {
21 intID, err := strconv.Atoi(v)
22 if err != nil {
23 return 0, err
24 }
25 ID = uint(intID)
26 }
27
28 if ID < minID || ID > maxID {
29 return 0, errors.New("ID out of range")
30 }
31
32 return ID, nil
33}
34
35// IP is an enhanced net.IP
36type IP struct {
37 netIP net.IP
38 Purpose []string
39}
40
41// IPFromNetIP creates a IP from a net.IP.
42func IPFromNetIP(netIP net.IP) IP {
43 var ip IP
44 ip.netIP = netIP
45 return ip
46}
47
48// IPFromString creates a new IP from a string IP address representation
49func IPFromString(v string) IP {
50 return IPFromNetIP(net.ParseIP(v))
51}
52
53// IPFromInt64 creates a new IP from a uint64 IP address representation
54func IPFromInt64(v uint64) IP {
55 var ip IP
56 ip.SetUInt64(v)
57 return ip
58}
59
60// To4 converts the IPv4 address ip to a 4-byte representation. If ip is not
61// an IPv4 address, To4 returns nil.
62func (ip IP) To4() net.IP {
63 return ip.netIP.To4()
64}
65
66// To16 converts the IP address ip to a 16-byte representation. If ip is not
67// an IP address (it is the wrong length), To16 returns nil.
68func (ip IP) To16() net.IP {
69 return ip.netIP.To16()
70}
71
72func (ip IP) String() string {
73 return ip.netIP.String()
74}
75
76// UInt64 returns a uint64 holding the IP address
77func (ip IP) UInt64() uint64 {
78 if len(ip.netIP) == 0 {
79 return uint64(0)
80 }
81
82 if ip.To4() != nil {
83 return uint64(binary.BigEndian.Uint32([]byte(ip.To4())))
84 }
85
86 return binary.BigEndian.Uint64([]byte(ip.To16()))
87}
88
89// SetUInt64 sets the IP value to v
90func (ip *IP) SetUInt64(v uint64) {
91 if len(ip.netIP) == 0 {
92 // If we don't have allocated storage make an educated guess
93 // at if the address we received is an IPv4 or IPv6 address.
94 if v == (v & 0x00000000ffffFFFF) {
95 // Guessing IPv4
96 ip.netIP = net.ParseIP("0.0.0.0")
97 } else {
98 ip.netIP = net.ParseIP("2001:4860:0:2001::68")
99 }
100 }
101
102 bb := new(bytes.Buffer)
103 var first int
104 if ip.To4() != nil {
105 binary.Write(bb, binary.BigEndian, uint32(v))
106 first = len(ip.netIP) - 4
107 } else {
108 binary.Write(bb, binary.BigEndian, v)
109 }
110 copy(ip.netIP[first:], bb.Bytes())
111}
112
113func PrettyJsonWriter(thing interface{}, w http.ResponseWriter) {
114 var out bytes.Buffer
115 b, err := json.MarshalIndent(thing, "", " ")
116 checkError(err)
117 out.Write(b)
118 out.WriteTo(w)
119}