packages feed

idna2008-1.0.0.0: internal/Text/IDNA2008/Internal/LabelForm.hs

-- |
-- Module      : Text.IDNA2008.Internal.LabelForm
-- Description : Per-label classification singleton.
-- Copyright   : (c) Viktor Dukhovni, 2026
-- License     : BSD-3-Clause
--
-- Maintainer  : ietf-dane@dukhovni.org
-- Stability   : unstable
--
-- The 'LabelForm' singleton type names the nine possible
-- classifications the parser can assign to a single label, plus
-- a tenth sentinel 'NoLabel' returned by
-- 'Text.IDNA2008.Internal.LabelInfo.getLabelForm' for indices
-- outside the parsed domain's label count.  The parser never
-- produces 'NoLabel' for a real label.
--
-- The companion type 'Text.IDNA2008.Internal.LabelFormSet'
-- represents unordered /sets/ of label forms.
{-# LANGUAGE PatternSynonyms #-}

module Text.IDNA2008.Internal.LabelForm
    ( LabelForm(.., LDH, RLDH, FAKEA, ALABEL, ULABEL, ATTRLEAF, OCTET
               , WILDLABEL, LAXULABEL, NoLabel)
    ) where

import Data.Word (Word8)

-- | A single per-label classification.  Use the pattern
-- singletons to construct or pattern-match.
newtype LabelForm = LabelForm_ Word8
    deriving (Eq, Ord)

-- | Letter-digit-hyphen, the conventional hostname alphabet.
-- Lowercase ASCII letters, digits, and the hyphen, with no
-- leading or trailing hyphen and no double-hyphen at positions
-- 3 and 4 (which would make it a Reserved-LDH or A-label).
pattern LDH :: LabelForm
pattern LDH = LabelForm_ 0

-- | Reserved LDH: an LDH-shaped label with @--@ at positions 3
-- and 4 whose first two characters are not (case-folded)
-- @\"xn\"@.  In practice these are pre-IDN registrations like
-- @\"l---l\"@, @\"cd--storage-shelves\"@.
pattern RLDH :: LabelForm
pattern RLDH = LabelForm_ 1

-- | An ACE-prefixed LDH label that does /not/ strictly
-- round-trip: its Punycode body decodes to something invalid
-- as an IDN label, or the re-encoding doesn't match the input.
pattern FAKEA :: LabelForm
pattern FAKEA = LabelForm_ 2

-- | An ACE-prefixed LDH label that strictly round-trips:
-- the Punycode body decodes cleanly, the decoded codepoints are
-- valid in an IDN, and re-encoding produces the same input bytes.
pattern ALABEL :: LabelForm
pattern ALABEL = LabelForm_ 3

-- | A label whose source contained at least one non-ASCII
-- character.  The library's parser accepts non-ASCII input,
-- validates each codepoint, and encodes the label to its
-- ACE-prefixed form for the wire.
pattern ULABEL :: LabelForm
pattern ULABEL = LabelForm_ 4

-- | An LDH-shaped label whose first character is @\'_\'@.  Used
-- by service-discovery records and by attribute-leaf naming
-- conventions: @\"_25._tcp\"@, @\"_dmarc\"@,
-- @\"_acme-challenge\"@, etc.
pattern ATTRLEAF :: LabelForm
pattern ATTRLEAF = LabelForm_ 5

-- | A label whose bytes are not all in the LDH alphabet.
-- Includes labels admitted via @\\DDD@ or @\\C@ escapes
-- regardless of UTF-8 validity, labels with non-LDH ASCII
-- (e.g. @\'$\'@, @\'+\'@), and labels containing non-ASCII
-- codepoints that aren't valid for IDN classification.
pattern OCTET :: LabelForm
pattern OCTET = LabelForm_ 6

-- | The single-byte wildcard label @\'*\'@.  Distinct from
-- 'OCTET' so callers that want to admit @\"*.example\"@
-- queries can do so without admitting arbitrary non-LDH bytes.
pattern WILDLABEL :: LabelForm
pattern WILDLABEL = LabelForm_ 7

-- | Like 'ULABEL' but the non-ASCII codepoints fail strict
-- U-label validation.
pattern LAXULABEL :: LabelForm
pattern LAXULABEL = LabelForm_ 8

-- | Sentinel value returned by
-- 'Text.IDNA2008.Internal.LabelInfo.getLabelForm' when the
-- index is outside the parsed domain's label count.  The parser
-- never produces 'NoLabel' for an actual label, and it is not
-- a member of any 'Text.IDNA2008.Internal.LabelFormSet'.
pattern NoLabel :: LabelForm
pattern NoLabel = LabelForm_ 9

{-# COMPLETE LDH, RLDH, FAKEA, ALABEL, ULABEL, ATTRLEAF, OCTET,
             WILDLABEL, LAXULABEL, NoLabel #-}

instance Show LabelForm where
    show LDH       = "LDH"
    show RLDH      = "RLDH"
    show FAKEA     = "FAKEA"
    show ALABEL    = "ALABEL"
    show ULABEL    = "ULABEL"
    show ATTRLEAF  = "ATTRLEAF"
    show OCTET     = "OCTET"
    show WILDLABEL = "WILDLABEL"
    show LAXULABEL = "LAXULABEL"
    show NoLabel   = "NoLabel"