A DomainName
represents a name in the domain name system.
A DomainName
represents a name in the domain name system.
Unlike the example in Programming in Scala/2e the elements of the domain name are stored in the same order
as used, i.e. as www.scalacraft.com
, not reversed.
This implementation is case sensitive which is at variance with the Wikipedia specification. If a convincing use case for case insensitivity arises this could be reconsidered. Expressed in code we have,
DomainName.opt("WWW") != DomainName.opt("www")
The v2 documentation provides details of the syntactic constraints placed on domain names.
Pattern matching is supported as the following example demonstrates,
"example.com" match { case DomainName(label1, label2) => label1 :: label2 :: Nil // List("example", "com") case _ => None }
Invalid domain names will not be matched.
"a.b-" match { case DomainName(label1, label2) => label1 :: label2 :: Nil case _ => None // None }
To match an arbitrary number of domain name labels use a pattern sequence,
"www.example.com" match { case DomainName(label, labels@_*) => labels // "example"::"com"::Nil }
Implicit conversions exist which allow an instance of DomainName
to be used when either a String
or Seq[String]
is required.
def countElements(seq: Seq[String]) = seq.length val dn = DomainName.opt("www", "example", "com").get val elemNo = countElements(dn) // 3
A conversion to the unconstrained version of this class is also available.
An IP4Address
represents an IP4 address.
An IP4Address
represents an IP4 address.
This class constrains the range of each byte to [0, 255].
Pattern matching is supported as the following example demonstrates,
"192.162.1.9" match { case IP4Address(_, _, b3, b4) => Some(256 * b3 + b4) // Some(265) case _ => None }
Implicit conversions exist which allow an instance of IP4Address
when a String
is required.
val ipa = IP4Address(b1, b2, b3, b4) val inet = java.v2.InetAddress.getByName(ipa)
A conversion to the unconstrained version of this class is also available.
IP6Address
A Port
represents an IP port.
A Port
represents an IP port.
The following constraints hold for instances of this class,
- portNumber
is in the range [0, 65535]
An instance can be created using a suitable overload of the opt
method.
val portOpt: Option[Port] = Port.opt(1908) val portOpt2: Option[Port] = Port.opt("40115")
When any class constraint is violated the result is None
.
Pattern matching is supported as the following examples demonstrate,
7 match { case Port(p) => p // 7 case _ => None }
The match target can be a string,
val s: String = ... s match { case Port(p) => p case _ => None }
Invalid ports are not matched,
-129 match { case Port(p) => p case _ => None // None }
Implicit conversions exists which allow an instance of Port
to be used when an Int
or String
is required.
val port = Port.opt(6006) val sa = port map { p => new InetSocketAddress(p) }
A conversion to the unconstrained version of this class is also available.
Domain classes related to networking
Domain Name Syntax
The syntactic constraints on a domain name are taken from Wikipedia: Domain Name, excerpted here for ease of reference.
Wikipedia
Domain names may be formed from the set of alphanumeric ASCII characters (a-z, A-Z, 0-9), but characters are case-insensitive. In addition the hyphen is permitted if it is surrounded by characters, digits or hyphens, although it is not to start or end a label.
The hierarchy of domains descends from the right to the left label in the name; each label to the left specifies a subdivision, or subdomain of the domain to the right. For example: the label example specifies a node example.com as a subdomain of the com domain, and www is a label to create www.example.com, a subdomain of example.com. This tree of labels may consist of 127 levels. Each label may contain from 1 to 63 octets. The empty label is reserved for the root node. The full domain name may not exceed a total length of 253 ASCII characters in its textual representation. In practice, some domain registries may have shorter limits.