(*---------------------------------------------------------------------------*
  INTERFACE  cf_ip6_addr.mli

  Copyright (c) 2003-2006, James H. Woodyatt
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions
  are met:

    Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.

    Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in
    the documentation and/or other materials provided with the
    distribution

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  OF THE POSSIBILITY OF SUCH DAMAGE. 
 *---------------------------------------------------------------------------*)


(** IPv6 addresses with attribute parameters for type safety.

    This module implements IPv6 addresses in an abstract type suitable for use
    with the {!Cf_nameinfo} module, the {!Cf_socket} module and its cognates
    for IPv6 transports.  Internally, the IPv6 address is represented as a
    boxed 16-byte custom block.  Externally, the IPv6 address abstract type is
    parameterized with a shadow attribute that constrains how it may be used
    depending on its address format.
*)

(** The type of IPv4 addresses, parameterized by address format attribute. *)
type -'a t

(** The shadow attribute type of IPv6 addresses of unknown format. *)
type opaque = [ `AF_INET6 ]

(** The type of IPv6 address formats. *)
type format =
    | Unspecified   (** ::0 *)
    | Unicast       (** ::1 to EFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF *)
    | Multicast     (** FF00::0 to FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF *)

(** The shadow attribute of the IPv6 unspecified address. *)
type unspecified = [ opaque | `X ]

(** The shadow attribute of unicast IPv6 addresses. *)
type unicast = [ opaque | `U ]

(** The shadow attribute of multicast IPv6 addresses. *)
type multicast = [ opaque | `M ]

(** Use [format a] to obtain the address format of the IPv6 address [a]. *)
val format: opaque t -> format

(** Use [is_unicast a] to validate that the IPv6 address [a] is a unicast
    address.  Raises [Failure] unless the address is a unicast address.
*)
val is_unicast: [> opaque ] t -> unicast t

(** Use [is_multicast a] to validate that the IPv6 address [a] is a multicast
    address.  Raises [Failure] unless the address is a multicast address.
*)
val is_multicast: [> opaque ] t -> multicast t

(** The type of unicast address formats. *)
type unicast_format =
    | U_unassigned  (** No format assigned. *)
    | U_reserved    (** Format is reserved for future assignment. *)
    | U_loopback    (** Loopback addresses. *)
    | U_v4compat    (** Compatible with IPv4 (deprecated). *)
    | U_v4mapped    (** IPv4 addresses mapped into IPv6 addresses. *)
    | U_link        (** Link-local scope *)
    | U_site        (** Site-local scope (deprecated). *)
    | U_uniqlocal   (** Unique local unicast (global scope). *)
    | U_global      (** Global scope. *)

(** Use [unicast_format a] to obtain the unicast format of the unicast IPv6
    address [a].
*)
val unicast_format: [> unicast ] t -> unicast_format

(** The shadow attribute of "v4-compat" unicast addresses *)
type v4compat = [ unicast | `V4C ]

(** Use [is_v4compat a] to obtain the opaque IPv4 address corresponding to the
    v4-compat IPv6 address.  Raises [Failure] if the address is not a v4-compat
    format address.
*)
val is_v4compat: [> unicast ] t -> Cf_ip4_addr.opaque Cf_ip4_addr.t

(** Use [to_v4compat a] to convert the unicast IPv4 address [a] to its
    v4-compat IPv6 address.
*)
val to_v4compat: [> Cf_ip4_addr.unicast ] Cf_ip4_addr.t -> v4compat t

(** The shadow attribute of "v4-mapped" unicast addresses *)
type v4mapped = [ unicast | `V4M ]

(** Use [is_v4mapped a] to obtain the opaque IPv4 address corresponding to the
    v4-mapped IPv6 address.  Raises [Failure] if the address is not a v4-mapped
    format address.
*)
val is_v4mapped: [> unicast ] t -> Cf_ip4_addr.opaque Cf_ip4_addr.t

(** Use [to_v4mapped a] to convert the unicast IPv4 address [a] to its
    v4-mapped IPv6 address.
*)
val to_v4mapped: [> Cf_ip4_addr.unicast ] Cf_ip4_addr.t -> v4mapped t

(** The type of IPv6 multicast address format flags. *)
type multicast_flag =
    | M_F_transient             (** Address is transiently allocated. *)
    | M_F_unassigned of int     (** Flag is reserved for future assignment. *)

(** The type of IPv6 multicast address scopes. *)
type multicast_scope =
    | M_S_node                  (** Node-only scope. *)
    | M_S_link                  (** Link-local scope. *)
    | M_S_site                  (** Site-local scope. *)
    | M_S_org                   (** Organization-local scope. *)
    | M_S_global                (** Global scope. *)
    | M_S_unassigned of int     (** Scope reserved for future assignment. *)

(** The shadow attribute of multicast group identifiers. *)
type multicast_group_id = [ opaque | `G ]

(** Use [to_multicast_components a] to obtain the scope, flags and group id
    of the IPv6 multicast address [a].
*)
val to_multicast_components:
    [> multicast ] t ->
    multicast_scope * multicast_flag list * multicast_group_id t

(** Use [of_multicast_components scope flags gid] to compose an IPv6 multicast
    address from the [scope], [flags] and [gid] components.
*)
val of_multicast_components:
    multicast_scope -> multicast_flag list -> multicast_group_id t ->
    multicast t

(** The unspecified IPv6 address, i.e. ::0 *)
val unspecified: unspecified t

(** The default loopback IPv6 unicast address, i.e. ::1 *)
val loopback: unicast t

(** The node-local all-nodes multicast address, i.e. ff01::1 *)
val node_local_all_nodes: multicast t

(** The link-local all-nodes multicast address, i.e. ff02::1 *)
val link_local_all_nodes: multicast t

(** The link-local all-routers multicast address, i.e. ff02::2 *)
val link_local_all_routers: multicast t

(** Use [equal a1 a2] to compare two IPv6 addresses for equality. *)
val equal: [> opaque ] t -> [> opaque ] t -> bool

(** Use [compare a1 a2] to compare the ordinality of two IPv6 addresses. *)
val compare: [> opaque ] t -> [> opaque ] t -> int

(** Use [pton s] to convert the string [s] containing an IPv6 address in
    numeric format to its equivalent opaque IPv6 address.  Returns [None] if
    the string is not in canonical numeric format.
*)
val pton: string -> opaque t option

(** Use [ntop a] to obtain a string representation of the IPv6 address [a]
    in canonical numeric format. *)
val ntop: [> opaque ] t -> string

(*--- End of File [ cf_af_inet6.mli ] ---*)
