package types import ( "bytes" "database/sql/driver" "fmt" "net" ) type ( // Subnet is used to parse a subnet parameter. Subnet net.IPNet // IP is used to parse an IP parameter. IP net.IP ) // UnmarshalJSON parses a value into a subnet. // // It is also checked if the provided IP matches the network address // of the subnet. func (s *Subnet) UnmarshalJSON(in []byte) error { in = bytes.Trim(in, `"`) ip, ipnet, err := net.ParseCIDR(string(in)) if err != nil { return fmt.Errorf("not a valid subnet") } if !ipnet.IP.Equal(ip) { return fmt.Errorf("provided IP is not a subnet") } *s = Subnet(*ipnet) return nil } // String returns the string representation of the subnet. // // The subnet is returned as the subnet address and prefix separated by `/` // as defined in RFC 4632 and RFC 4291. func (s *Subnet) String() string { return (*net.IPNet)(s).String() } // Value implements the database Value interface. // // This function is needed so that a subnet can be inserted into // the database without much casting. func (s *Subnet) Value() (driver.Value, error) { return s.String(), nil } func (i *IP) UnmarshalJSON(in []byte) error { in = bytes.Trim(in, `"`) ip := net.ParseIP(string(in)) if ip == nil { return fmt.Errorf("not a valid ip") } *i = IP(ip) return nil }