DSL

Use the following imports for the examples:

import com.github.mkroli.dns4s._
import com.github.mkroli.dns4s.dsl._
import com.github.mkroli.dns4s.section._
import com.github.mkroli.dns4s.section.resource._

Header

ID

// Creation
val msg: Message = Query ~ Id(123)
// msg: Message = Message(
//   header = HeaderSection(
//     id = 123,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )

// Matching
val id = msg match {
  case Id(id) => id
}
// id: Int = 123

QR

// Creation
val query: Message = Query
// query: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val response1: Message = Response
// response1: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val response2: Message = Response(query)
// response2: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )

// Matching
val qr = query match {
  case Query(msg)    => "query"
  case Response(msg) => "response"
}
// qr: String = "query"

Opcode

// Creation
val query1: Message = Query ~ StandardQuery
// query1: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val query2: Message = Query ~ InverseQuery
// query2: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 1,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val query3: Message = Query ~ ServerStatusRequest
// query3: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 2,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )

// Matching
val op = query1 match {
  case StandardQuery()       => "standard-query"
  case InverseQuery()        => "inverse-query"
  case ServerStatusRequest() => "server-status-request"
}
// op: String = "standard-query"

AA

// Creation
val response: Message = Response ~ AuthoritativeAnswer
// response: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = true,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )

// Matching
val aa = response match {
  case AuthoritativeAnswer() => true
  case _ => false
}
// aa: Boolean = true

TC

// Creation
val response: Message = Response ~ Truncation
// response: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = true,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )

// Matching
val tc = response match {
  case Truncation() => true
  case _ => false
}
// tc: Boolean = true

RD

// Creation
val query: Message = Query ~ RecursionDesired
// query: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )

// Matching
val rd = query match {
  case RecursionDesired() => true
  case _ => false
}
// rd: Boolean = true

RA

// Creation
val response: Message = Response ~ RecursionAvailable
// response: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = true,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )

// Matching
val ra = response match {
  case RecursionAvailable() => true
  case _ => false
}
// ra: Boolean = true

RCODE

// Creation
val response1: Message = Response ~ NoError
// response1: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val response2: Message = Response ~ FormatError
// response2: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 1,
//     qdcount = 0,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val response3: Message = Response ~ ServerFailure
// response3: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 2,
//     qdcount = 0,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val response4: Message = Response ~ NameError
// response4: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 3,
//     qdcount = 0,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val response5: Message = Response ~ NotImplemented
// response5: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 4,
//     qdcount = 0,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val response6: Message = Response ~ Refused
// response6: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 5,
//     qdcount = 0,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )

// Matching
val rCode = response1 match {
  case Response(r) ~ NoError()        => "no-error"
  case Response(r) ~ FormatError()    => "format-error"
  case Response(r) ~ ServerFailure()  => "server-failure"
  case Response(r) ~ NameError()      => "name-error"
  case Response(r) ~ NotImplemented() => "not-implemented"
  case Response(r) ~ Refused()        => "refused"
}
// rCode: String = "no-error"

Sections

Question section

// Creation
val query: Message = Query ~ Questions()
// query: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )

// Matching
val questions = query match {
  case Query(_) ~ Questions(questions) => questions
}
// questions: Seq[QuestionSection] = List()

QNAME

// Creation
val query1: Message = Query ~ Questions(QName("example.com"))
// query1: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 1, qclass = 1)),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val query2: Message = Query ~ Questions(QName("example.com"), QName("www.example.com"))
// query2: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 2,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 1, qclass = 1),
//     QuestionSection(qname = "www.example.com", qtype = 1, qclass = 1)
//   ),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )

// Matching
val names = query2 match {
  case Query(_) ~ Questions(QName(name1) :: QName(name2) :: Nil) => (name1, name2)
}
// names: (String, String) = ("example.com", "www.example.com")

QTYPE

// Creation
val query: Message = Query ~ Questions(QName("example.com") ~ QType(ResourceRecord.typeTXT))
// query: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 16, qclass = 1)
//   ),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )

val queryA:        Message = Query ~ Questions(QName("example.com") ~ TypeA)
// queryA: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 1, qclass = 1)),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryNS:       Message = Query ~ Questions(QName("example.com") ~ TypeNS)
// queryNS: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 2, qclass = 1)),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryMD:       Message = Query ~ Questions(QName("example.com") ~ TypeMD)
// queryMD: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 3, qclass = 1)),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryMF:       Message = Query ~ Questions(QName("example.com") ~ TypeMF)
// queryMF: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 4, qclass = 1)),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryCNAME:    Message = Query ~ Questions(QName("example.com") ~ TypeCNAME)
// queryCNAME: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 5, qclass = 1)),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val querySOA:      Message = Query ~ Questions(QName("example.com") ~ TypeSOA)
// querySOA: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 6, qclass = 1)),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryMB:       Message = Query ~ Questions(QName("example.com") ~ TypeMB)
// queryMB: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 7, qclass = 1)),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryMG:       Message = Query ~ Questions(QName("example.com") ~ TypeMG)
// queryMG: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 8, qclass = 1)),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryMR:       Message = Query ~ Questions(QName("example.com") ~ TypeMR)
// queryMR: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 9, qclass = 1)),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryNULL:     Message = Query ~ Questions(QName("example.com") ~ TypeNULL)
// queryNULL: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 10, qclass = 1)
//   ),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryWKS:      Message = Query ~ Questions(QName("example.com") ~ TypeWKS)
// queryWKS: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 11, qclass = 1)
//   ),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryPTR:      Message = Query ~ Questions(QName("example.com") ~ TypePTR)
// queryPTR: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 12, qclass = 1)
//   ),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryHINFO:    Message = Query ~ Questions(QName("example.com") ~ TypeHINFO)
// queryHINFO: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 13, qclass = 1)
//   ),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryMINFO:    Message = Query ~ Questions(QName("example.com") ~ TypeMINFO)
// queryMINFO: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 14, qclass = 1)
//   ),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryMX:       Message = Query ~ Questions(QName("example.com") ~ TypeMX)
// queryMX: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 15, qclass = 1)
//   ),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryTXT:      Message = Query ~ Questions(QName("example.com") ~ TypeTXT)
// queryTXT: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 16, qclass = 1)
//   ),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryAAAA:     Message = Query ~ Questions(QName("example.com") ~ TypeAAAA)
// queryAAAA: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 28, qclass = 1)
//   ),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val querySRV:      Message = Query ~ Questions(QName("example.com") ~ TypeSRV)
// querySRV: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 33, qclass = 1)
//   ),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryNAPTR:    Message = Query ~ Questions(QName("example.com") ~ TypeNAPTR)
// queryNAPTR: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 35, qclass = 1)
//   ),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryOPT:      Message = Query ~ Questions(QName("example.com") ~ TypeOPT)
// queryOPT: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 41, qclass = 1)
//   ),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryAXFR:     Message = Query ~ Questions(QName("example.com") ~ TypeAXFR)
// queryAXFR: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 252, qclass = 1)
//   ),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryMAILB:    Message = Query ~ Questions(QName("example.com") ~ TypeMAILB)
// queryMAILB: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 253, qclass = 1)
//   ),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryMAILA:    Message = Query ~ Questions(QName("example.com") ~ TypeMAILA)
// queryMAILA: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 254, qclass = 1)
//   ),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryAsterisk: Message = Query ~ Questions(QName("example.com") ~ TypeAsterisk)
// queryAsterisk: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 255, qclass = 1)
//   ),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )

// Matching
val `type` = query match {
  case Query(q) ~ Questions(QName(name) ~ TypeA()        :: Nil) => "A"
  case Query(q) ~ Questions(QName(name) ~ TypeNS()       :: Nil) => "NS"
  case Query(q) ~ Questions(QName(name) ~ TypeMD()       :: Nil) => "MD"
  case Query(q) ~ Questions(QName(name) ~ TypeMF()       :: Nil) => "MF"
  case Query(q) ~ Questions(QName(name) ~ TypeCNAME()    :: Nil) => "CNAME"
  case Query(q) ~ Questions(QName(name) ~ TypeSOA()      :: Nil) => "SOA"
  case Query(q) ~ Questions(QName(name) ~ TypeMB()       :: Nil) => "MB"
  case Query(q) ~ Questions(QName(name) ~ TypeMG()       :: Nil) => "MG"
  case Query(q) ~ Questions(QName(name) ~ TypeMR()       :: Nil) => "MR"
  case Query(q) ~ Questions(QName(name) ~ TypeNULL()     :: Nil) => "NULL"
  case Query(q) ~ Questions(QName(name) ~ TypeWKS()      :: Nil) => "WKS"
  case Query(q) ~ Questions(QName(name) ~ TypePTR()      :: Nil) => "PTR"
  case Query(q) ~ Questions(QName(name) ~ TypeHINFO()    :: Nil) => "HINFO"
  case Query(q) ~ Questions(QName(name) ~ TypeMINFO()    :: Nil) => "MINFO"
  case Query(q) ~ Questions(QName(name) ~ TypeMX()       :: Nil) => "MX"
  case Query(q) ~ Questions(QName(name) ~ TypeTXT()      :: Nil) => "TXT"
  case Query(q) ~ Questions(QName(name) ~ TypeAAAA()     :: Nil) => "AAAA"
  case Query(q) ~ Questions(QName(name) ~ TypeSRV()      :: Nil) => "SRV"
  case Query(q) ~ Questions(QName(name) ~ TypeNAPTR()    :: Nil) => "NAPTR"
  case Query(q) ~ Questions(QName(name) ~ TypeOPT()      :: Nil) => "OPT"
  case Query(q) ~ Questions(QName(name) ~ TypeAXFR()     :: Nil) => "AXFR"
  case Query(q) ~ Questions(QName(name) ~ TypeMAILB()    :: Nil) => "MAILB"
  case Query(q) ~ Questions(QName(name) ~ TypeMAILA()    :: Nil) => "MAILA"
  case Query(q) ~ Questions(QName(name) ~ TypeAsterisk() :: Nil) => "Asterisk"

  case Query(q) ~ Questions(QName(name) ~ QType(t) :: Nil) => t.toString
}
// `type`: String = "TXT"

QCLASS

// Creation
val query: Message = Query ~ Questions(QName("example.com") ~ QType(ResourceRecord.typeA) ~ QClass(ResourceRecord.classIN))
// query: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 1, qclass = 1)),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )

val queryIN:       Message = Query ~ Questions(QName("example.com") ~ TypeA ~ ClassIN)
// queryIN: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 1, qclass = 1)),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryCS:       Message = Query ~ Questions(QName("example.com") ~ TypeA ~ ClassCS)
// queryCS: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 1, qclass = 2)),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryCH:       Message = Query ~ Questions(QName("example.com") ~ TypeA ~ ClassCH)
// queryCH: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 1, qclass = 3)),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryHS:       Message = Query ~ Questions(QName("example.com") ~ TypeA ~ ClassHS)
// queryHS: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 1, qclass = 4)),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )
val queryAsterisk: Message = Query ~ Questions(QName("example.com") ~ TypeA ~ ClassAsterisk)
// queryAsterisk: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 1, qclass = 255)
//   ),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )

// Matching
val qclass = query match {
  case Query(q) ~ Questions(QName(name) ~ QType(t) ~ QClass(c) :: Nil) => c

  case Query(q) ~ Questions(QName(name) ~ TypeA() ~ ClassIN() :: Nil) => ???
  case Query(q) ~ Questions(QName(name) ~ TypeA() ~ ClassCS() :: Nil) => ???
  case Query(q) ~ Questions(QName(name) ~ TypeA() ~ ClassCH() :: Nil) => ???
  case Query(q) ~ Questions(QName(name) ~ TypeA() ~ ClassHS() :: Nil) => ???
  case Query(q) ~ Questions(QName(name) ~ TypeA() ~ ClassAsterisk() :: Nil) => ???
}
// qclass: Int = 1

Answer section

// Creation
val response: Message = Response ~ Questions(QName("example.com") ~ TypeA) ~ Answers()
// response: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 1, qclass = 1)),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )

// Matching
val answers = response match {
  case Response(r) ~ Answers(answers) => answers
}
// answers: Seq[ResourceRecord] = List()

Authority records section

// Creation
val response: Message = Response ~ Questions(QName("example.com") ~ TypeA) ~ Authority()
// response: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 1, qclass = 1)),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )

// Matching
val authority = response match {
  case Response(r) ~ Authority(authority) => authority
}
// authority: Seq[ResourceRecord] = List()

Additional records section

// Creation
val response: Message = Response ~ Questions(QName("example.com") ~ TypeA) ~ Additional()
// response: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 1, qclass = 1)),
//   answer = List(),
//   authority = List(),
//   additional = List()
// )

// Matching
val additional = response match {
  case Response(r) ~ Additional(additional) => additional
}
// additional: Seq[ResourceRecord] = List()

Resource record

NAME

// Creation
val response: Message = Response ~ Questions(QName("example.com") ~ TypeA) ~ Answers(RRName("example.com"))
// response: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 1, qclass = 1)),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 10,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )

// Matching
val name = response match {
  case Response(r) ~ Answers(RRName(name) :: Nil) => name
}
// name: String = "example.com"

TYPE

// Creation
val response:         Message = Response ~ Answers(RRName("example.com") ~ RRType(ResourceRecord.typeTXT))
// response: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 16,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )

val responseA:        Message = Response ~ Answers(RRName("example.com") ~ TypeA)
// responseA: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 1,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseNS:       Message = Response ~ Answers(RRName("example.com") ~ TypeNS)
// responseNS: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 2,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseMD:       Message = Response ~ Answers(RRName("example.com") ~ TypeMD)
// responseMD: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 3,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseMF:       Message = Response ~ Answers(RRName("example.com") ~ TypeMF)
// responseMF: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 4,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseCNAME:    Message = Response ~ Answers(RRName("example.com") ~ TypeCNAME)
// responseCNAME: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 5,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseSOA:      Message = Response ~ Answers(RRName("example.com") ~ TypeSOA)
// responseSOA: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 6,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseMB:       Message = Response ~ Answers(RRName("example.com") ~ TypeMB)
// responseMB: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 7,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseMG:       Message = Response ~ Answers(RRName("example.com") ~ TypeMG)
// responseMG: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 8,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseMR:       Message = Response ~ Answers(RRName("example.com") ~ TypeMR)
// responseMR: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 9,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseNULL:     Message = Response ~ Answers(RRName("example.com") ~ TypeNULL)
// responseNULL: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 10,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseWKS:      Message = Response ~ Answers(RRName("example.com") ~ TypeWKS)
// responseWKS: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 11,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responsePTR:      Message = Response ~ Answers(RRName("example.com") ~ TypePTR)
// responsePTR: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 12,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseHINFO:    Message = Response ~ Answers(RRName("example.com") ~ TypeHINFO)
// responseHINFO: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 13,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseMINFO:    Message = Response ~ Answers(RRName("example.com") ~ TypeMINFO)
// responseMINFO: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 14,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseMX:       Message = Response ~ Answers(RRName("example.com") ~ TypeMX)
// responseMX: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 15,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseTXT:      Message = Response ~ Answers(RRName("example.com") ~ TypeTXT)
// responseTXT: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 16,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseAAAA:     Message = Response ~ Answers(RRName("example.com") ~ TypeAAAA)
// responseAAAA: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 28,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseSRV:      Message = Response ~ Answers(RRName("example.com") ~ TypeSRV)
// responseSRV: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 33,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseNAPTR:    Message = Response ~ Answers(RRName("example.com") ~ TypeNAPTR)
// responseNAPTR: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 35,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseOPT:      Message = Response ~ Answers(RRName("example.com") ~ TypeOPT)
// responseOPT: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 41,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseAXFR:     Message = Response ~ Answers(RRName("example.com") ~ TypeAXFR)
// responseAXFR: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 252,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseMAILB:    Message = Response ~ Answers(RRName("example.com") ~ TypeMAILB)
// responseMAILB: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 253,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseMAILA:    Message = Response ~ Answers(RRName("example.com") ~ TypeMAILA)
// responseMAILA: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 254,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseCAA:      Message = Response ~ Answers(RRName("example.com") ~ TypeCAA)
// responseCAA: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 257,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseAsterisk: Message = Response ~ Answers(RRName("example.com") ~ TypeAsterisk)
// responseAsterisk: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 255,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )

// Matching
val rtype = response match {
  case Response(r) ~ Answers(RRName(name) ~ TypeA()        :: Nil) => "A"
  case Response(r) ~ Answers(RRName(name) ~ TypeNS()       :: Nil) => "NS"
  case Response(r) ~ Answers(RRName(name) ~ TypeMD()       :: Nil) => "MD"
  case Response(r) ~ Answers(RRName(name) ~ TypeMF()       :: Nil) => "MF"
  case Response(r) ~ Answers(RRName(name) ~ TypeCNAME()    :: Nil) => "CNAME"
  case Response(r) ~ Answers(RRName(name) ~ TypeSOA()      :: Nil) => "SOA"
  case Response(r) ~ Answers(RRName(name) ~ TypeMB()       :: Nil) => "MB"
  case Response(r) ~ Answers(RRName(name) ~ TypeMG()       :: Nil) => "MG"
  case Response(r) ~ Answers(RRName(name) ~ TypeMR()       :: Nil) => "MR"
  case Response(r) ~ Answers(RRName(name) ~ TypeNULL()     :: Nil) => "NULL"
  case Response(r) ~ Answers(RRName(name) ~ TypeWKS()      :: Nil) => "WKS"
  case Response(r) ~ Answers(RRName(name) ~ TypePTR()      :: Nil) => "PTR"
  case Response(r) ~ Answers(RRName(name) ~ TypeHINFO()    :: Nil) => "HINFO"
  case Response(r) ~ Answers(RRName(name) ~ TypeMINFO()    :: Nil) => "MINFO"
  case Response(r) ~ Answers(RRName(name) ~ TypeMX()       :: Nil) => "MX"
  case Response(r) ~ Answers(RRName(name) ~ TypeTXT()      :: Nil) => "TXT"
  case Response(r) ~ Answers(RRName(name) ~ TypeAAAA()     :: Nil) => "AAAA"
  case Response(r) ~ Answers(RRName(name) ~ TypeSRV()      :: Nil) => "SRV"
  case Response(r) ~ Answers(RRName(name) ~ TypeNAPTR()    :: Nil) => "NAPTR"
  case Response(r) ~ Answers(RRName(name) ~ TypeOPT()      :: Nil) => "OPT"
  case Response(r) ~ Answers(RRName(name) ~ TypeAXFR()     :: Nil) => "AXFR"
  case Response(r) ~ Answers(RRName(name) ~ TypeMAILB()    :: Nil) => "MAILB"
  case Response(r) ~ Answers(RRName(name) ~ TypeMAILA()    :: Nil) => "MAILA"
  case Response(r) ~ Answers(RRName(name) ~ TypeCAA()      :: Nil) => "CAA"
  case Response(r) ~ Answers(RRName(name) ~ TypeAsterisk() :: Nil) => "Asterisk"

  case Response(r) ~ Answers(RRName(name) ~ RRType(t)      :: Nil) => t.toString
}
// rtype: String = "TXT"

CLASS

// Creation
val response:         Message = Response ~ Answers(RRName("example.com") ~ RRClass(ResourceRecord.classIN))
// response: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 10,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )

val responseIN:       Message = Response ~ Answers(RRName("example.com") ~ ClassIN)
// responseIN: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 10,
//       class = 1,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseCS:       Message = Response ~ Answers(RRName("example.com") ~ ClassCS)
// responseCS: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 10,
//       class = 2,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseCH:       Message = Response ~ Answers(RRName("example.com") ~ ClassCH)
// responseCH: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 10,
//       class = 3,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseHS:       Message = Response ~ Answers(RRName("example.com") ~ ClassHS)
// responseHS: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 10,
//       class = 4,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val responseAsterisk: Message = Response ~ Answers(RRName("example.com") ~ ClassAsterisk)
// responseAsterisk: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 10,
//       class = 255,
//       ttl = 3600L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )

// Matching
val `class` = response match {
  case Response(q) ~ Answers(ClassIN()       :: Nil) => "IN"
  case Response(q) ~ Answers(ClassCS()       :: Nil) => "CS"
  case Response(q) ~ Answers(ClassCH()       :: Nil) => "CH"
  case Response(q) ~ Answers(ClassHS()       :: Nil) => "HS"
  case Response(q) ~ Answers(ClassAsterisk() :: Nil) => "Asterisk"

  case Response(q) ~ Answers(RRClass(c)       :: Nil) => c.toString
}
// `class`: String = "IN"

TTL

// Creation
val response: Message = Response ~ Questions(QName("example.com") ~ TypeA) ~ Answers(RRName("example.com") ~ RRType(ResourceRecord.typeTXT) ~ RRClass(ResourceRecord.classIN) ~ RRTtl(123))
// response: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 1, qclass = 1)),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 16,
//       class = 1,
//       ttl = 123L,
//       rdata = UnknownResource(bytes = List(), type = 10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )

// Matching
val ttl = response match {
  case Response(r) ~ Answers(RRName(name) ~ RRType(t) ~ RRClass(c) ~ RRTtl(ttl) :: Nil) => ttl
}
// ttl: Long = 123L

Resource records

ARecord

// Creation
val addr: java.net.Inet4Address = java.net.InetAddress.getByAddress(Array.fill[Byte](4)(0)).asInstanceOf[java.net.Inet4Address]
// addr: java.net.Inet4Address = /0.0.0.0
val response1: Message = Response ~ Questions(QName("example.com") ~ TypeA) ~ Answers(ARecord(addr))
// response1: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 1, qclass = 1)),
//   answer = List(
//     ResourceRecord(
//       name = "",
//       type = 1,
//       class = 1,
//       ttl = 3600L,
//       rdata = AResource(address = /0.0.0.0)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val response2: Message = Response ~ Questions(QName("example.com") ~ TypeA) ~ Answers(ARecord(Array[Byte](1, 2, 3, 4)))
// response2: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 1, qclass = 1)),
//   answer = List(
//     ResourceRecord(
//       name = "",
//       type = 1,
//       class = 1,
//       ttl = 3600L,
//       rdata = AResource(address = /1.2.3.4)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val response3: Message = Response ~ Questions(QName("example.com") ~ TypeA) ~ Answers(ARecord("1.2.3.4"))
// response3: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 1, qclass = 1)),
//   answer = List(
//     ResourceRecord(
//       name = "",
//       type = 1,
//       class = 1,
//       ttl = 3600L,
//       rdata = AResource(address = /1.2.3.4)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )

// Matching
val address = response1 match {
  case Response(_) ~ Answers(ARecord(r) :: Nil) => r.address
}
// address: java.net.Inet4Address = /0.0.0.0

AAAARecord

// Creation
val addr: java.net.Inet6Address = java.net.InetAddress.getByAddress(Array.fill[Byte](16)(0)).asInstanceOf[java.net.Inet6Address]
// addr: java.net.Inet6Address = /0:0:0:0:0:0:0:0
val response1: Message = Response ~ Questions(QName("example.com") ~ TypeAAAA) ~ Answers(AAAARecord(addr))
// response1: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 28, qclass = 1)
//   ),
//   answer = List(
//     ResourceRecord(
//       name = "",
//       type = 28,
//       class = 1,
//       ttl = 3600L,
//       rdata = AAAAResource(address = /0:0:0:0:0:0:0:0)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val response2: Message = Response ~ Questions(QName("example.com") ~ TypeAAAA) ~ Answers(AAAARecord(Array[Byte](1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)))
// response2: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 28, qclass = 1)
//   ),
//   answer = List(
//     ResourceRecord(
//       name = "",
//       type = 28,
//       class = 1,
//       ttl = 3600L,
//       rdata = AAAAResource(address = /102:304:506:708:90a:b0c:d0e:f10)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val response3: Message = Response ~ Questions(QName("example.com") ~ TypeAAAA) ~ Answers(AAAARecord("0123:4567:89ab:cdef:0123:4567:89ab:cdef"))
// response3: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 28, qclass = 1)
//   ),
//   answer = List(
//     ResourceRecord(
//       name = "",
//       type = 28,
//       class = 1,
//       ttl = 3600L,
//       rdata = AAAAResource(address = /123:4567:89ab:cdef:123:4567:89ab:cdef)
//     )
//   ),
//   authority = List(),
//   additional = List()
// )

// Matching
val address = response1 match {
  case Response(_) ~ Answers(AAAARecord(r) :: Nil) => r.address
}
// address: java.net.Inet6Address = /0:0:0:0:0:0:0:0

CNameRecord

// Creation
val response: Message = Response ~ Questions(QName("www.example.com") ~ TypeCNAME) ~ Answers(CNameRecord("example.com"))
// response: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "www.example.com", qtype = 5, qclass = 1)
//   ),
//   answer = List(
//     ResourceRecord(
//       name = "",
//       type = 5,
//       class = 1,
//       ttl = 3600L,
//       rdata = CNameResource(cname = "example.com")
//     )
//   ),
//   authority = List(),
//   additional = List()
// )

// Matching
val cname = response match {
  case Response(_) ~ Answers(CNameRecord(r) :: Nil) => r.cname
}
// cname: String = "example.com"

MXRecord

// Creation
val response: Message = Response ~ Questions(QName("example.com") ~ TypeMX) ~ Answers(MXRecord(1, "example.com"))
// response: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 15, qclass = 1)
//   ),
//   answer = List(
//     ResourceRecord(
//       name = "",
//       type = 15,
//       class = 1,
//       ttl = 3600L,
//       rdata = MXResource(preference = 1, exchange = "example.com")
//     )
//   ),
//   authority = List(),
//   additional = List()
// )

// Matching
val (preference, exchange) = response match {
  case Response(_) ~ Answers(MXRecord(r) :: Nil) => (r.preference, r.exchange)
}
// preference: Int = 1
// exchange: String = "example.com"

NAPTRRecord

// Creation
val response: Message = Response ~ Questions(QName("example.com") ~ TypeNAPTR) ~ Answers(NAPTRRecord(1, 1, "A", "", "!^.*$!example.com!", ""))
// response: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 35, qclass = 1)
//   ),
//   answer = List(
//     ResourceRecord(
//       name = "",
//       type = 35,
//       class = 1,
//       ttl = 3600L,
//       rdata = NAPTRResource(
//         order = 1,
//         preference = 1,
//         flags = "A",
//         services = "",
//         regexp = "!^.*$!example.com!",
//         replacement = ""
//       )
//     )
//   ),
//   authority = List(),
//   additional = List()
// )

// Matching
val (order, preference, flags, services, regexp, replacement) = response match {
  case Response(_) ~ Answers(NAPTRRecord(r) :: Nil) => (r.order, r.preference, r.flags, r.services, r.regexp, r.replacement)
}
// order: Int = 1
// preference: Int = 1
// flags: String = "A"
// services: String = ""
// regexp: String = "!^.*$!example.com!"
// replacement: String = ""

OPTRecord

// Creation
val response: Message = Response ~ Questions(QName("example.com") ~ TypeOPT) ~ Additional(OPTRecord(Nil))
// response: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 1
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 41, qclass = 1)
//   ),
//   answer = List(),
//   authority = List(),
//   additional = List(
//     ResourceRecord(
//       name = "",
//       type = 41,
//       class = 1,
//       ttl = 3600L,
//       rdata = OPTResource(options = List())
//     )
//   )
// )

// Matching
val optRecord = response match {
  case Response(_) ~ Additional(OPTRecord(r) :: Nil) => r
}
// optRecord: OPTResource = OPTResource(options = List())
ClientSubnetOption
// Creation
val response: Message = Response ~ Additional(OPTRecord(ClientSubnetOption(OPTResource.ClientSubnetOPTOptionData.familyIPv4, 24, 0, java.net.InetAddress.getByName("1.2.3.0")) :: Nil))
// response: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 0,
//     ancount = 0,
//     nscount = 0,
//     arcount = 1
//   ),
//   question = List(),
//   answer = List(),
//   authority = List(),
//   additional = List(
//     ResourceRecord(
//       name = "",
//       type = 41,
//       class = 1,
//       ttl = 3600L,
//       rdata = OPTResource(
//         options = List(
//           OPTOption(
//             code = 8,
//             data = ClientSubnetOPTOptionData(
//               family = 1,
//               sourcePrefixLength = 24,
//               scopePrefixLength = 0,
//               address = /1.2.3.0
//             )
//           )
//         )
//       )
//     )
//   )
// )

// Matching
val (family, sourcePrefixLength, scopePrefixLength, address) = response match {
  case Response(_) ~ Additional(OPTRecord(OPTResource(ClientSubnetOption(OPTResource.ClientSubnetOPTOptionData(family, sourcePrefixLength, scopePrefixLength, address)) :: Nil)) :: Nil) => (family, sourcePrefixLength, scopePrefixLength, address)
}
// family: Int = 1
// sourcePrefixLength: Int = 24
// scopePrefixLength: Int = 0
// address: java.net.InetAddress = /1.2.3.0

NSRecord

// Creation
val response: Message = Response ~ Questions(QName("example.com") ~ TypeNS) ~ Answers(NSRecord("example.com"))
// response: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 2, qclass = 1)),
//   answer = List(
//     ResourceRecord(
//       name = "",
//       type = 2,
//       class = 1,
//       ttl = 3600L,
//       rdata = NSResource(nsdname = "example.com")
//     )
//   ),
//   authority = List(),
//   additional = List()
// )

// Matching
val nsdname = response match {
  case Response(_) ~ Answers(NSRecord(r) :: Nil) => r.nsdname
}
// nsdname: String = "example.com"

PTRRecord

// Creation
val response: Message = Response ~ Questions(QName("example.com") ~ TypePTR) ~ Answers(PTRRecord("example.com"))
// response: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 12, qclass = 1)
//   ),
//   answer = List(
//     ResourceRecord(
//       name = "",
//       type = 12,
//       class = 1,
//       ttl = 3600L,
//       rdata = PTRResource(ptrdname = "example.com")
//     )
//   ),
//   authority = List(),
//   additional = List()
// )

// Matching
val ptrdname = response match {
  case Response(_) ~ Answers(PTRRecord(r) :: Nil) => r.ptrdname
}
// ptrdname: String = "example.com"

HInfoRecord

// Creation
val response: Message = Response ~ Questions(QName("example.com") ~ TypeHINFO) ~ Answers(HInfoRecord("CPU", "Linux"))
// response: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 13, qclass = 1)
//   ),
//   answer = List(
//     ResourceRecord(
//       name = "",
//       type = 13,
//       class = 1,
//       ttl = 3600L,
//       rdata = HInfoResource(cpu = "CPU", os = "Linux")
//     )
//   ),
//   authority = List(),
//   additional = List()
// )

// Matching
val (cpu, os) = response match {
  case Response(_) ~ Answers(HInfoRecord(r) :: Nil) => (r.cpu, r.os)
}
// cpu: String = "CPU"
// os: String = "Linux"

TXTRecord

// Creation
val response: Message = Response ~ Questions(QName("example.com") ~ TypeTXT) ~ Answers(TXTRecord("Test", "test", "tesT"))
// response: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 16, qclass = 1)
//   ),
//   answer = List(
//     ResourceRecord(
//       name = "",
//       type = 16,
//       class = 1,
//       ttl = 3600L,
//       rdata = TXTResource(txt = ArraySeq("Test", "test", "tesT"))
//     )
//   ),
//   authority = List(),
//   additional = List()
// )

// Matching
val txt = response match {
  case Response(_) ~ Answers(TXTRecord(r) :: Nil) => r.txt
}
// txt: Seq[String] = ArraySeq("Test", "test", "tesT")

SOARecord

// Creation
val response: Message = Response ~ Questions(QName("example.com") ~ TypeSOA) ~ Answers(SOARecord("example.com", "admin.example.com", 2015122401L, 3600L, 1800L, 604800L, 600L))
// response: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 6, qclass = 1)),
//   answer = List(
//     ResourceRecord(
//       name = "",
//       type = 6,
//       class = 1,
//       ttl = 3600L,
//       rdata = SOAResource(
//         mname = "example.com",
//         rname = "admin.example.com",
//         serial = 2015122401L,
//         refresh = 3600L,
//         retry = 1800L,
//         expire = 604800L,
//         minimum = 600L
//       )
//     )
//   ),
//   authority = List(),
//   additional = List()
// )

// Matching
val (mname, rname, serial, refresh, retry, expire, minimum) = response match {
  case Response(_) ~ Answers(SOARecord(r) :: Nil) => (r.mname, r.rname, r.serial, r.refresh, r.retry, r.expire, r.minimum)
}
// mname: String = "example.com"
// rname: String = "admin.example.com"
// serial: Long = 2015122401L
// refresh: Long = 3600L
// retry: Long = 1800L
// expire: Long = 604800L
// minimum: Long = 600L

CAARecord

// Creation
val response: Message = Response ~ Questions(QName("example.com") ~ TypeCAA) ~ Answers(RRName("example.com") ~ CAARecord.Issue("cert-authority.org"))
// response: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 257, qclass = 1)
//   ),
//   answer = List(
//     ResourceRecord(
//       name = "example.com",
//       type = 257,
//       class = 1,
//       ttl = 3600L,
//       rdata = IssueResource(
//         value = "cert-authority.org",
//         issuerCritical = false
//       )
//     )
//   ),
//   authority = List(),
//   additional = List()
// )

// Matching
val value = response match {
  case Response(_) ~ Answers(CAARecord.Issue(r) :: Nil) => r.value
}
// value: String = "cert-authority.org"

Misc

DnsClassName

// Matching
val msg: Message = Response ~ Questions(QName("example.com") ~ TypeTXT) ~ Answers(TXTRecord("Test", "test", "tesT"))
// msg: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 16, qclass = 1)
//   ),
//   answer = List(
//     ResourceRecord(
//       name = "",
//       type = 16,
//       class = 1,
//       ttl = 3600L,
//       rdata = TXTResource(txt = ArraySeq("Test", "test", "tesT"))
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val (qclass, aclass) = msg match {
  case Response(_) ~ Questions(DnsClassName(qclass) :: Nil) ~ Answers(DnsClassName(aclass) :: Nil) => (qclass, aclass)
}
// qclass: String = "IN"
// aclass: String = "IN"

DnsTypeName

The DnsTypeName object can be used to extract a String representation of a Question or a ResourceRecord.

// Matching
val msg: Message = Response ~ Questions(QName("example.com") ~ TypeTXT) ~ Answers(TXTRecord("Test", "test", "tesT"))
// msg: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = true,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 1,
//     nscount = 0,
//     arcount = 0
//   ),
//   question = List(
//     QuestionSection(qname = "example.com", qtype = 16, qclass = 1)
//   ),
//   answer = List(
//     ResourceRecord(
//       name = "",
//       type = 16,
//       class = 1,
//       ttl = 3600L,
//       rdata = TXTResource(txt = ArraySeq("Test", "test", "tesT"))
//     )
//   ),
//   authority = List(),
//   additional = List()
// )
val (qtype, atype) = msg match {
  case Response(_) ~ Questions(DnsTypeName(qtype) :: Nil) ~ Answers(DnsTypeName(atype) :: Nil) => (qtype, atype)
}
// qtype: String = "TXT"
// atype: String = "TXT"

EDNS

// Creation
val query1: Message = Query ~ Questions(QName("example.com") ~ TypeA) ~ EDNS()
// query1: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 1
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 1, qclass = 1)),
//   answer = List(),
//   authority = List(),
//   additional = List(
//     ResourceRecord(
//       name = "",
//       type = 41,
//       class = 4096,
//       ttl = 0L,
//       rdata = OPTResource(options = List())
//     )
//   )
// )
val query2: Message = Query ~ Questions(QName("example.com") ~ TypeA) ~ EDNS(4096)
// query2: Message = Message(
//   header = HeaderSection(
//     id = 0,
//     qr = false,
//     opcode = 0,
//     aa = false,
//     tc = false,
//     rd = true,
//     ra = false,
//     rcode = 0,
//     qdcount = 1,
//     ancount = 0,
//     nscount = 0,
//     arcount = 1
//   ),
//   question = List(QuestionSection(qname = "example.com", qtype = 1, qclass = 1)),
//   answer = List(),
//   authority = List(),
//   additional = List(
//     ResourceRecord(
//       name = "",
//       type = 41,
//       class = 4096,
//       ttl = 0L,
//       rdata = OPTResource(options = List())
//     )
//   )
// )

// Matching
val size = query1 match {
  case Query(_) ~ Questions(q) ~ EDNS(size) => size
}
// size: Int = 4096