=================================
`pyfixbuf` --- Class Descriptions
=================================

.. rubric:: Class Overview

The data for single flow is represented in pyfixbuf by the
:class:`~pyfixbuf.Record` class.  A Record contains one or more
:class:`~pyfixbuf.Record.Field` objects, where each Field describes some
aspect of the flow.

The format of a flow record is flexible and is described by a Template,
represented in pyfixbuf by the :class:`~pyfixbuf.Template` class.  A template
contains references to one or more Information Elements
(:class:`~pyfixbuf.InfoElement`), where each element describes some aspect of
the flow, such as ``sourceIPv4Address``.  The elements referenced by a
template correspond to the fields in the :class:`~pyfixbuf.Record`.  The
:class:`~pyfixbuf.InfoElementSpec` class is used to specify the Information
Elements used by a Template.

libfixbuf and Pyfixbuf support :rfc:`6313` which defines object types to hold
structured data.  A basicList (:class:`~pyfixbuf.BL`) may contain multiple
instances of a single Information Element.  A subTemplateList
(:class:`~pyfixbuf.STL`) contains zero or more :class:`~!pyfixbuf.Record`
instances that use that a single :class:`~!pyfixbuf.Template`.  Finally, the
subTemplateMultiList (:class:`~pyfixbuf.STML`) type holds
:class:`~!pyfixbuf.Record` instances that may use different
:class:`~!pyfixbuf.Template` descriptions.  In an :class:`~!pyfixbuf.STML`, a
group of Records that use the same :class:`~!pyfixbuf.Template` are
represented by the :class:`~pyfixbuf.STMLEntry` class.

An exporting process is created with the :class:`~pyfixbuf.Exporter` class,
and a collecting process is created with the :class:`~pyfixbuf.Collector`
class if it is file-based or the :class:`~pyfixbuf.Listener` class if it is
socket-based.  Internally, the :class:`~!pyfixbuf.Listener` creates a new
:class:`~!pyfixbuf.Collector` object when a new connection is made to the
socket.

The interface between a :class:`~!pyfixbuf.Collector` or an
:class:`~!pyfixbuf.Exporter` and the :class:`~!pyfixbuf.Record` and
:class:`~!pyfixbuf.Template` objects is managed by two classes:

* The message buffer, :class:`~pyfixbuf.Buffer`, is used to read data from a
  Collector and write data to a Exporter.

* The :class:`~pyfixbuf.Session` manages Templates and other state, such as
  message sequence numbers.

The universe of information elements (:class:`~pyfixbuf.InfoElement`) is
maintained by an Information Model (:class:`~pyfixbuf.InfoModel`).  An
InfoModel instance contains the information elements `defined by IANA`_.  The
InfoModel may be expanded by defining enterprise-specific elements, such as
those `defined by CERT`_ (see also the :mod:`pyfixbuf.cert` module).  The CERT
elements are required when reading data produced by YAF_ or `super_mediator`_.

The :class:`~pyfixbuf.DataType`, :class:`~pyfixbuf.Units`, and
:class:`~pyfixbuf.Semantic` classes are enumerations that describe properties
of an :class:`~pyfixbuf.InfoElement`.

.. _defined by CERT: https://tools.netsa.cert.org/cert-ipfix-registry/index.html
.. _defined by IANA: https://www.iana.org/assignments/ipfix/ipfix.xhtml
.. _libfixbuf:  https://tools.netsa.cert.org/fixbuf/index.html
.. _super_mediator: https://tools.netsa.cert.org/super_mediator/index.html
.. _YAF: https://tools.netsa.cert.org/yaf/index.html

.. automodule:: pyfixbuf

Record
================

A :class:`!Record` is one of the "core" interfaces to the IPFIX data through
libfixbuf.  This is the main object for manipulating the data prior
to export and following import.

.. autoclass:: Record(model: InfoModel[, template: Template = None[, record: Record = None]])

   .. automethod:: add_element(key_name: str[, type: DataType = DataType.OCTET_ARRAY[, element_name: str = None[, length: int = 0]]])

   .. automethod:: add_element_list(name_list: Iterable[str])

   .. automethod:: clear_all_lists()

   .. automethod:: clear()

   .. automethod:: init_basic_list(basic_list_key: str[, count: int = 0[, element_name: str = None]])

   .. automethod:: clear_basic_list(basic_list_key: str)

   .. automethod:: __getitem__(key: Union[str, int]) -> Any

   .. automethod:: __setitem__ (key: Union[str, int], value: Any)

   .. automethod:: copy(other: Record)

   .. automethod:: is_list(key: str) -> bool

   .. automethod:: get(key: str, default: Any = None) -> Any

   .. automethod:: get_field(key: str) -> Record.Field

   .. automethod:: get_stl_list_entry(key: str) -> STL

   .. automethod:: get_stml_list_entry(key: str) -> STML

   .. automethod:: as_dict() -> Dict[Union[str, Tuple(str, int)], Any]

   .. automethod:: __len__() -> int

   .. automethod:: __contains__(item: str) -> bool

   .. automethod:: set_template(template: Template)

   .. automethod:: __iter__() -> Iterator[Any]

   .. automethod:: iterfields() -> Iterator[Record.Field]

   .. automethod:: matches_template(template: Template, exact: bool = False) -> bool

   .. automethod:: count(element_name: str) -> int

   .. attribute:: template : Template

      Returns the :class:`Template` used by this :class:`!Record`.

Record.Field
==============

.. class:: Record.Field(name: str, instance: int, ie: InfoElement, length: int, value: Any)

   Represents a complete value field in a :class:`Record`, and is implemented
   as a subclass of :class:`collection.namedtuple`.  This is the type of
   object returned by the :meth:`Record.iterfields` method.  A
   :class:`!Record.Field` object includes the following attributes:

   .. attribute:: name : str

      The field name provided as the `key` parameter to
      :meth:`Record.add_element`.  For a :class:`Record` built from a
      :class:`Template`, this is the name is the :class:`InfoElement`.

   .. attribute:: instance : int

      An integer that is non-zero when :attr:`!name` is not unique.  The value
      represents the number of times :attr:`!name` occurs in the
      :class:`Record` before this one.

   .. attribute:: ie : InfoElement

      The canonical :class:`InfoElement` that describes this value.

   .. attribute:: length : int

      The length of this field specified to :meth:`Record.add_element` or in
      the :class:`InfoElementSpec` associated with the :class:`!Record`\ 's
      :class:`Template`.  May be different than the length specified in the
      :class:`InfoElement` due to reduced length encoding.

   .. attribute:: value : Any

      The value of this field.


Template
======================

The :class:`!Template` type implements an IPFIX Template or an IPFIX Options
Template.  IPFIX templates contain one or more Information Elements
(:class:`InfoElement`).
If a certain sequence of elements is desired, each Information Element
(:class:`InfoElementSpec`) must be added to the template in the desired
order.  Templates are stored by Template ID and type (internal, external)
per domain in a :class:`Session`.  The valid range of Template IDs is
256 to 65535.  Templates are given a template ID when they are added to
a :class:`!Session`. The only difference between Data Templates and Options
Templates is that Options Templates have a scope associated with them,
which gives the context of reported Information Elements in the Data
Records.

An Internal Template is how fixbuf decides what the data should look
like when it is transcoded.  For this reason, an internal template should
match the corresponding :class:`Record`, in terms of the order of Information
Elements. An External Template is sent before
the exported data so that the Collecting Process is able to process
IPFIX messages without necessarily knowing the interpretation of all data
records.

.. autoclass:: Template(model: InfoModel[, type: bool = False])

   An Information Model (:class:`InfoModel`) is needed to allocate and
   initialize a new Template.

   .. automethod:: copy() -> Template

   .. automethod:: add_spec(spec: InfoElementSpec)

   .. automethod:: add_spec_list(specs: Iterable[InfoElementSpec])

   .. automethod:: add_element(name: str)

   .. automethod:: get_indexed_ie(index: int) -> InfoElement

   .. automethod:: get_context() -> Any

   .. automethod:: __contains__(element: Union[InfoElement, InfoElementSpec, str, int]) -> bool

   .. automethod:: __getitem__(key: Union[str, int]) -> InfoElementSpec

   .. automethod:: __len__() -> int

   .. automethod:: __iter__() -> Iterator[InfoElementSpec]

   .. automethod:: ie_iter() -> Iterator[InfoElement]

   .. attribute:: scope : int

      Returns the scope associated with the :class:`!Template`.
      Setting scope to zero sets the scope to encompass the entire
      template.  Setting the scope to ``None`` removes the scope.

   .. attribute:: template_id : int

      Returns the template ID associated with the :class:`!Template`.
      Template ID can only be changed by adding the template to a
      :class:`Session`.

   .. attribute:: type : bool

      Returns ``True`` if template is an Information Element Type Information
      Template.  Returns ``False`` otherwise.  This attribute may not be
      changed.

   .. attribute:: infomodel : InfoModel

      Returns the :class:`InfoModel` associated with the Template.  This
      attribute may not be changed.

   .. attribute:: read_only : bool

      Returns ``True`` if this template has been added to a :class:`Session`.
      This attribute may not be set.

Examples::

   >>> tmpl = pyfixbuf.Template(model)
   >>> spec = pyfixbuf.InfoElementSpec("sourceTransportPort")
   >>> spec2 = pyfixbuf.InfoElementSpec("destinationTransportPort")
   >>> tmpl.add_spec(spec)
   >>> tmpl.add_spec(spec2)
   >>> tmpl2 = pyfixbuf.Template(model)
   >>> tmpl2.add_spec_list([pyfixbuf.InfoElementSpec("fooname"),
                       pyfixbuf.InfoElementSpec("barname")])
   >>> tmpl2.scope = 2
   >>> if "sourceTransportPort" in tmpl:
   >>>    print "yes"
   yes


BL
===============

A basicList is a list of zero or more instances of an Information Element.
Examples include a list of port numbers, or a list of host names.
The BL object acts similar to a Python list with additional attributes.

.. autoclass:: BL(model: InfoModel, element: Union[InfoElement, InfoElementSpec, str][, count: int = 0[, semantic: int = 0]])

   .. automethod:: __len__() -> int

   .. automethod:: __iter__() -> Iterator[Any]

   .. automethod:: __getitem__(index: int) -> Any

   .. automethod:: __setitem__(key: int, value: Any)

   .. automethod:: copy(other: Iterable[Any])

   .. automethod:: __contains__(item: Any) -> bool

   .. automethod:: __str__() -> str

   .. automethod:: __eq__(other: list) -> bool

   .. method:: clear()

      Clears and frees the basicList data.

   .. attribute:: semantic : int

       The `structured data semantic value`_ for this :class:`!BL`.

       .. _structured data semantic value: https://www.iana.org/assignments/ipfix/ipfix.xhtml#ipfix-structured-data-types-semantics

   .. attribute:: element : InfoElement

       The :class:`InfoElement` associated with this :class:`!BL` that was set
       when the class:`!BL` was created.  This attribute may not be changed.


Decoding Examples::

        >>> bl = rec["basicList"]
        >>> for items in bl:
        ...    print str(items) + '\n'
        ... bl.clear()

Encoding Examples::

         >>> bl = BL(model, "httpUserAgent", 2)
         >>> bl[0] = "Mozilla/Firefox"
         >>> bl[1] = "Safari5.0"
         >>> rec["basicList"] = bl
         >>> if "Safari5.0" in bl:
         ...     print "Apple"
         Apple
         >>> print bl
         ["Mozilla/Firefox", "Safari5.0"]


STL
===============

A subTemplateList is a list of zero or more instances of a
structured data type where each entry corresponds to a
single template.  Since a single template is associated
with an :class:`!STL`, a :class:`Record` must also be associated with the
:class:`!STL`.  Access each entry (a :class:`!Record`) in the list by
iterating through the :class:`!STL`.

.. autoclass:: STL([record: Record = None, key_name: str = None])

   .. automethod:: set_record(record: Record)

   .. automethod:: __contains__(name: str) -> bool

   .. automethod:: entry_init(record: Record, template: Template[, count: int = 0])

   .. automethod:: __iter__() -> Iterator[Record]

   .. automethod:: next() -> Record

   .. automethod:: iter_records(tmpl_id: int = 0) -> Iterator[Records]

   .. automethod:: clear()

   .. automethod:: __getitem__(item: Union[int, str]) -> Any

   .. automethod:: __setitem__(key: int, value: Record)

   .. automethod:: __len__() -> int

   .. attribute:: template_id : int

        The template ID of the :class:`Template` used for this :class:`!STL`.

   .. attribute:: semantic : int

       The `structured data semantic value`_ for this :class:`!STL`.

       .. _structured data semantic value: https://www.iana.org/assignments/ipfix/ipfix.xhtml#ipfix-structured-data-types-semantics

Decoding Examples::

        >>> stl = rec["dnsList"]
        >>> stl.set_record(dnsRecord)
        >>> for dnsRecord in stl:
        ...     dnsRecord = dnsRecord.as_dict()
        ...     for key,value in dnsRecord.items():
        ...         print key + ": " + str(value) + '\n'
        ... stl.clear()

Encoding Examples::

         >>> stl = STL()
         >>> stl.entry_init(dnsRecord, dnsTemplate, 2)
         >>> dnsRecord["dnsName"] = "google.com"
         >>> dnsRecord["rrType"] = 1
         >>> stl[0] = dnsRecord
         >>> dnsRecord["dnsName"] = "ns.google.com"
         >>> dnsRecord["rrType"] = 2
         >>> stl[1] = dnsRecord
         >>> rec["subTemplateList"] = stl

STML
=================

A subTemplateMultiList is a list of zero or more instances of
a structured data record, where the data records do not necessarily
have to reference the same template.  A subTemplateMultiList is made
up of one or more :class:`STMLEntry` objects.  Each :class:`!STMLEntry` in the
:class:`!STML` typically has a different template associated with it, but that
is not a requirement.  The data in the :class:`!STML` is accessed by iterating
through each :class:`!STMLEntry` in the list and setting a :class:`Record` on
the :class:`!STMLEntry`.

.. autoclass:: STML([record: Record = None[, key_name:str = None[, type_count: int = -1]]])

   .. automethod:: clear()

   .. automethod:: __iter__() -> Iterator[STMLEntry]

   .. automethod:: next() -> STMLEntry

   .. automethod:: iter_records(tmpl_id: int = 0) -> Iterator[Records]

   .. automethod:: __len__() -> int

   .. automethod:: __contains__(name: str) -> bool

   .. automethod:: __getitem__(index: int) -> STMLEntry

   .. automethod:: __setitem__(key: int, value: Iterable[Record])

   .. attribute:: semantic : int

       The `structured data semantic value`_ for this :class:`!STML`.

       .. _structured data semantic value: https://www.iana.org/assignments/ipfix/ipfix.xhtml#ipfix-structured-data-types-semantics

Decode Examples::

     >>> stml = my_rec["subTemplateMultiList"]
     >>> for entry in stml:
     ...        if "tcpSequenceNumber" in entry:
     ...           entry.set_record(tcprec)
     ...           for tcp_record in entry:
     ...               tcp_record = tcp_record.as_dict()
     ...               for key,value in tcp_record.items()
     ...                   print key + ": " + str(value) + '\n'

Encode Examples::

     >>> stml = STML(type_count=3)
     >>> stml.entry_init(rec, template, 2) #init first entry to 2 with template
     >>> rec["sourceTransportPort"] = 3
     >>> rec["destinationTransportPort"] = 5
     >>> stml[0][0] = rec
     >>> rec["sourceTransportPort"] = 6
     >>> rec["destinationTransportPort"] = 7
     >>> stml[0][1] = rec
     >>> stml[1][0] = rec2       #init second entry to 1 item using rec2
     >>> stml[2].entry_init(rec3, template3, 0) #init third entry to 0


STMLEntry
=====================

Each :class:`STML` consists of one or more :class:`!STMLEntry` objects.  Each
:class:`!STMLEntry` is associated with a :class:`Template`, and therefore
should have a corresponding :class:`Record`.  An :class:`!STMLEntry` can
contain zero or more instances of the associated :class:`Record`.

.. autoclass:: STMLEntry(stml: STML)

   .. automethod:: entry_init(record: Record, template: Template[, count: int = 0])

   .. automethod:: set_record(record: Record)

   .. automethod:: __contains__(name: str) -> bool

   .. automethod:: set_template(template: Template)

   .. automethod:: __iter__() -> Iterator[Record]

   .. automethod:: next() -> Record

   .. automethod:: __getitem__(item: Union[int, str]) -> Any

   .. automethod:: __setitem__(key: int, value: Record)

   .. automethod:: __len__() -> int

   .. attribute:: template_id : int

      The Template ID of the :class:`Template` that corresponds to this
      :class:`!STMLEntry` in the :class:`STML`.

Examples::

        >>> stml = my_rec["subTemplateMultiList"]
        >>> for entry in stml:
        ...     if "tcpSequenceNumber" in entry:
        ...        entry.set_record(tcp_rec)
        ...        for tcp_record in entry:
        ...            tcp_record = tcp_record.as_dict()
        ...            for key,value in tcp_record.items():
        ...                print key + ": " + str(value) + '\n'
        ...     elif entry.template_id == 0xCE00:
        ...        entry.set_record(dns_rec)
        ...
        >>> stml.clear()


Buffer
==============

The :class:`!Buffer` implements a transcoding IPFIX Message buffer for both
export and collection.  The :class:`!Buffer` is one of the "core" interfaces
to the fixbuf library.  Each :class:`!Buffer` must be initialized to do either
collecting or exporting.

.. autoclass:: Buffer([record: Record = None[, auto: bool = False]])

   .. automethod:: init_collection(session: Session, collector: Collector)

   .. automethod:: init_export(session: Session, exporter: Exporter)

   .. automethod:: set_internal_template(template_id: int)

   .. automethod:: set_export_template(template_id: int)

   .. automethod:: next_record(record: Record) -> Record

   .. automethod:: next([record: Record = None]) -> Record

   .. automethod:: __iter__() -> Iterator[Record]

   .. automethod:: set_record(record: Record)

   .. automethod:: next_template() -> Template

   .. automethod:: get_template() -> Template

   .. automethod:: append(rec: Record[, length: int])

   .. automethod:: write_ie_options_record(name: str, template: Template)

   .. automethod:: auto_insert()

   .. automethod:: ignore_options(ignore: bool)

   .. method:: emit()

      Writes any pending :class:`Record` objects in the :class:`!Buffer` to
      the :class:`Exporter`.

   .. method:: free()

      Frees the :class:`!Buffer`. This method may be invoked when using a
      :class:`!Buffer` for export to flush and close the stream.

Examples::

        >>> buf = pyfixbuf.Buffer(my_rec)
        >>> buf.init_collection(session, collector)
        >>> buf.set_internal_template(999)
        >>> for data in buf:
        ...     data = data.as_dict()
        ...     for key,value in data.items()
        ...         print key + ":" + str(value) + '\n'

Examples::

        >>> buf = pyfixbuf.Buffer(my_rec)
        >>> buf.init_export(session, exporter)
        >>> buf.set_internal_template(999)
        >>> buf.set_external_template(999)
        >>> session.export_templates()
        >>> while count < 10:
        ...       my_rec['sourceIPv4Address'] = "192.168.3.2"
        ...       my_rec['destinationIPv4Address'] = "192.168.4.5"
        ...       buf.append(my_rec)
        >>> buf.emit()

Examples::

        >> buf = pyfixbuf.Buffer(auto=True)
        >> buf.init_collection(session, collector)
        >> for data in buf:
        ...    data = data.as_dict()
        ...    for key,value in data.items()
        ...        print key + ":" + str(value) + '\n'


Session
=====================

The state of an IPFIX Transport Session is maintained in the :class:`!Session`
object.  This includes all IPFIX Message Sequence Number tracking, and
internal and external template management.  A :class:`!Session` is associated
with an :class:`InfoModel`.  :class:`Template` instances must be added before
collecting (via a :class:`Collector` or :class:`Listener`) or exporting (see
:class:`Exporter`) any data.

.. autoclass:: Session(model: InfoModel)

   .. automethod:: add_template(template: Template[, template_id: int = 0]) -> int

   .. automethod:: add_internal_template(template: Template[, template_id: int = 0]) -> int

   .. automethod:: add_external_template(template: Template[, template_id: int = 0]) -> int

   .. automethod:: decode_only(id_list: Iterable[int])

   .. automethod:: ignore_templates(id_list: Iterable[int])

   .. automethod:: add_template_pair(external_template_id: int, internal_template_id: int)

   .. method:: export_templates()

      Exports the templates associated with this :class:`!Session`.  This is
      necessary for an exporting session (see :class:`Exporter`) and must be
      called before any records are appended to the :class:`Buffer`.
      :class:`!Buffer` must already have a :class:`!Session` associated with
      it using :meth:`Buffer.init_export`.

   .. automethod:: get_template(template_id: int[, internal: bool = False]) -> Template

   .. automethod:: add_template_callback(callback: Callable[[Session, Template, Any], Any])

   .. attribute:: domain : int

      The observation domain on the :class:`!Session`.

Examples::

        >>> session = pyfixbuf.Session(model)
        >>> session.add_internal_template(289, tmpl)
        >>> auto_id = session.add_external_template(0, tmpl)
        >>> session.decode_only([256, 257])

Collector
======================

An :class:`!Collector` maintains the necessary information for the connection
to a corresponding Exporting Process.  A :class:`!Collector` is used for
reading from an IPFIX file.  See :class:`Listener` for collecting IPFIX over a
network.

.. autoclass:: Collector()

   .. automethod:: init_file(filename: str)

Examples::

   >>> collector = pyfixbuf.Collector()
   >>> collector.init_file("path/to/in.ipfix")


Exporter
=====================

An :class:`!Exporter` maintains the information needed for its connection to a
corresponding Collecting Process.  An :class:`!Exporter` may be created to
write to IPFIX files or to connect via the network using one of the supported
IPFIX transport protocols.

.. autoclass:: Exporter()

   .. automethod:: init_file(filename: str)

   .. automethod:: init_net(hostname: str[, transport: str = "tcp"[, port: int = 4739]])

Examples::

  >>> exporter = pyfixbuf.Exporter()
  >>> exporter.init_file("/path/to/out.ipfix")
  >>> exporter2 = pyfixbuf.Exporter()
  >>> exporter2.init_net("localhost", "udp", 18000)


Listener
====================

The :class:`!Listener` manages the passive collection used to listen for
connections from Exporting Processes.

.. autoclass:: Listener(session: Session, hostname: str[, transport: str = "tcp"[, port: int = 4739]])

   .. automethod:: wait([record: Record = None]) -> Buffer


InfoModel
======================

The :class:`!InfoModel` type implements an IPFIX Information Model
(:rfc:`7012`) which holds the known Information Elements
(:class:`InfoElement`).

libfixbuf_ adds, by default, the `IANA managed Information Elements`_ to the
Information Model.  IANA's Information Elements have a enterprise number of 0;
a non-zero enterprise number is called a private enterprise number (PEN).

To process data from YAF_ or `super_mediator`_, enterprise-specific
information elements must be loaded into the information model.  These
information elements use the CERT PEN, 6871.  One may load all CERT defined
information elements into an :class:`!InfoModel`, *model*, by importing the
:mod:`pyfixbuf.cert` package and running
:meth:`pyfixbuf.cert.add_elements_to_model` with *model* as its argument.

There are two alternate ways to add those elements to an :class:`!InfoModel`:

#. Download the `XML file`_ that defines those elements and invoke the model's
   :meth:`InfoModel.read_from_xml_file` method.

#. Invoke :meth:`InfoModel.add_element_list` on the model and pass it one of
   the :mod:`pyfixbuf.yaflists` variables.

.. _libfixbuf: https://tools.netsa.cert.org/fixbuf/index.html
.. _XML file: https://tools.netsa.cert.org/cert-ipfix-registry/index.html
.. _IANA managed Information Elements: https://www.iana.org/assignments/ipfix/ipfix.xhtml
.. _super_mediator: https://tools.netsa.cert.org/super_mediator/index.html
.. _YAF: https://tools.netsa.cert.org/yaf/index.html

.. autoclass:: InfoModel( )

   .. automethod:: add_element(element: InfoElement)

   .. automethod:: add_element_list(elements: Iterable[InfoElement]))

   .. automethod:: get_element_length(name: str[, type: int]) -> length

   .. automethod:: get_element([name: str[, id: int[, ent: int]]]) -> InfoElement

   .. automethod:: get_element_type(name: str) -> DataType

   .. automethod:: add_options_element(rec: Record)

   .. automethod:: read_from_xml_data(xml_data: Any)

   .. automethod:: read_from_xml_file(filename: str)

Examples::

        >>> model = pyfixbuf.InfoModel()
        >>> model.add_element(foo);
        >>> model.add_element_list([foo, bar, flo])
        >>> model.add_element_list(pyfixbuf.yaflists.YAF_DNS_LIST) # adds all YAF DNS DPI elements
        >>> length = model.get_element_length("sourceTransportPort")
        >>> print length
        2


InfoElement
=======================

An Information Element describes a single piece of data in a :class:`Template`
and the :class:`Record` it describes.  An IPFIX Information Model
(:class:`InfoModel`) holds all Information Elements.  Each Information Element
consists of a unique and meaningful name, an enterprise number, a numeric
identifier, a length, and a data type (:class:`DataType`).  The enterprise
number is 0 for information elements defined by IANA.  A non-zero enterprise
number is called a private enterprise number (PEN).

Giving an :class:`!InfoElement` an :class:`!DataType` allows Python to return
the appropriate type of object when the value is requested.  Otherwise, the
value of the :class:`!InfoElement` is :class:`bytearray`.  If the type is
DataType.STRING or one of the list values, the IE length should be
VARLEN. :class:`!InfoElement`\ s that have type DataType.OCTET_ARRAY may or
may not be variable length.

Units (:class:`~pyfixbuf.Units`), semantics (:class:`~pyfixbuf.Semantic`),
minimum value, maximum value, and description are all optional parameters to
further describe an information element.  If the process is exporting
Information Element Type Option Records (:rfc:`5610`), this information may
help the collecting process identify the type of information contained in the
value of an Information Element.

.. class:: InfoElement(name: str, enterprise_number: int, id: int[, length: int = VARLEN[, reversible: bool = False[, endian: bool = False[, type: DataType = DataType.OCTET_ARRAY[, units: Units = Units.NONE[, min: int = 0[, max: int = 0[, semantic: Semantic = Semantic.DEFAULT[, description: str = None]]]]]]]]])

   Creates a new Information Element (IE) using the given *name*,
   *enterprise_number*, and *id*, and optional *length*, *reversible* flag,
   *endian* flag, *datatype*, *units*, *min*, *max*, *semantic*, and
   *description*.  An Information Element identifies a type of data to be
   stored and transmitted via IPFIX.

   If no *length* is provided, the IE is defined as having a variable
   length.  All Strings should be variable length.

   If *endian* is ``True``, the IE is assumed to be an integer and will be
   converted to and from network byte order upon transcoding.

   If *reversible* is ``True``, a second IE is created for the same
   information in the reverse direction. (The reversed IE's name is created by
   capitalizing the first character of *name* and prepending the string
   ``reverse``.)

   If *type* is set, pyfixbuf will know how to print values of this type.
   Otherwise the type of the element will be DataType.OCTET_ARRAY and it is
   returned as a Python :class:`bytearray`.  The *type* may be a
   :class:`DataType` value or an integer.

   *units* optionally defines the units of an Information Element.  See
   :class:`Units` for the available units.

   *min* optionally defines the minimum value of an Information Element.

   *max* optionally defines the maximum value of an Information Element.

   *semantic* optionally defines the semantics of an Information Element.  See
   :class:`Semantic` for the known semantics.

   *description* optionally contains a human-readable description of an
   Information Element.

   .. attribute:: name : str

      The name, a string, associated with the InfoElement.

   .. attribute:: enterprise_number : int

      The Enterprise Number associated with the InfoElement.  Default
      Information Elements have a enterprise number
      of 0. :attr:`!enterprise_number` is a 32-bit unsigned integer
      (1--4,294,967,295).

   .. attribute:: id : int

      The Information Element ID that, with the enterprise number, uniquely
      identifies the Information Element. :attr:`!id` is an unsigned 15-bit
      integer (1--32767).

   .. attribute:: length : int

      The length of this Information Element as defined in the Information
      Model.  The lengths of elements having :attr:`type` DataType.STRING,
      DataType.OCTET_ARRAY, and DataType.LIST are 65535 (``VARLEN``).

   .. attribute:: type : DataType

      The data type associated with the Information Element.  The values are
      stored in the :class:`DataType` enumeration.  If type is not defined,
      the default type is 0, DataType.OCTET_ARRAY.  If the Information Element
      is defined as VARLEN, the default type is 14, DataType.STRING.

   .. attribute:: units : Units

      The units associated with the Information Element.  The values are
      stored in the :class:`Uints` enumeration.  If units are not defined, the
      default is Units.NONE.

   .. attribute:: min : int

      If a range is defined with the Information Element, min is the minimum
      value accepted.  Valid values are 0 - 2^64-1.

   .. attribute:: max : int

      If a range is defined for an Information Element, max is the maximum
      value accepted.  Valid values are 0 - 2^64-1.

   .. attribute:: semantic : Semantic

      Semantic value for an Information Element.  The values are stored in the
      :class:`Semantic` enumeration.  The default semantic is 0,
      Semantic.DEFAULT.

   .. attribute:: description : str

      Description of an Information Element.  This is a string.  Default is
      None.

   .. attribute:: reversible : bool

      ``True`` if an Information Element is defined as reversible.

   .. attribute:: endian : bool

      ``True`` if an Information Element is defined as numeric value that
      should potentially be byte-swapped when transcoding to or from network
      byte order.

   .. method:: as_dict() -> dict

      Returns a dictionary of key value pairs suitable for use as keyword
      arguments to :class:`!InfoElement`\ 's constructor.

   .. attribute:: ent : int

      An alias for :attr:`enterprise_number`.

Examples::

        >>> foo = pyfixbuf.InfoElement('fooname', CERT_PEN, 722, units=pyfixbuf.Units.WORDS)
        >>> bar = pyfixbuf.InfoElement('barname', 123, 565, 1, reversible=True, endian=True)
        >>> foo2 = pyfixbuf.InfoElement('fooname2', 0, 888, 3, type=pyfixbuf.DataType.OCTET_ARRAY)
        >>> flo = pyfixbuf.InfoElement('flo_element', 0, 452, 8, endian=True, type=8)


DataType
===========================

The :class:`!DataType` class holds the values for the `IPFIX Information
Element Data Types`_ defined by Section 3.1 of :rfc:`7012`.  This class may
not be instantiated, and all methods are static.

   .. _IPFIX Information Element Data Types: https://www.iana.org/assignments/ipfix/ipfix.xhtml#ipfix-information-element-data-types

.. autoclass:: DataType

   .. automethod:: get_name(value: int) -> str

   .. automethod:: to_string(value: int) -> str

   .. automethod:: by_name(name: String) -> DataType

   .. automethod:: check_type(data_type: int, value: Any) -> bool

   .. automethod:: get_length(data_type: int) -> int

   .. automethod:: refine_type_for_length(data_type: int, len: int) -> DataType

   .. automethod:: supports_RLE(data_type: int) -> bool

Semantic
===========================

The :class:`!Semantic` class holds the values for the `IPFIX Information
Element Semantics`_ defined by Section 3.2 of :rfc:`7012` and Section 3.10 of
:rfc:`5610`.  This class may not be instantiated, and all methods are static.

   .. _IPFIX Information Element Semantics: https://www.iana.org/assignments/ipfix/ipfix.xhtml#ipfix-information-semantics

.. autoclass:: Semantic

   .. automethod:: get_name(value: int) -> String

   .. automethod:: to_string(value: int) -> String

   .. automethod:: by_name(name: String) -> Semantic

Units
===========================

The :class:`!Units` class holds the values for the `IPFIX Information Element
Units`_ initially defined by Section 3.7 of :rfc:`5610`.  This class may not
be instantiated, and all methods are static.

   .. _IPFIX Information Element Units: https://www.iana.org/assignments/ipfix/ipfix.xhtml#ipfix-information-element-units

.. autoclass:: Units

   .. automethod:: get_name(value: int) -> String

   .. automethod:: to_string(value: int) -> String

   .. automethod:: by_name(name: String) -> Units


InfoElementSpec
===========================

An Information Element Specification (:class:`!InfoElementSpec`) is used to
name an Information Element (:class:`InfoElement`) for inclusion in a
:class:`Template`.  The Information Element must have already been defined and
added to the Information Model (:class:`InfoModel`).  An
:class:`!InfoElementSpec` contains the exact name of the defined Information
Element and an optional length override.

.. class:: InfoElementSpec(name: str[, length: int = 0])

   Creates a new Information Element Specification using the given *name*,
   and optional override *length*.  An IPFIX Template is made up of one or
   more :class:`!InfoElementSpec`\ s.

   The given *name* must be a defined Information Element
   (:class:`InfoElement`) in the Information Model (:class:`InfoModel`) before
   adding the :class:`!InfoElementSpec` to a :class:`Template`.

   If *length* is nonzero, it is used instead of the default length of
   this Information Element for reduced-length encoding.  Not all Information
   Element data types support reduced-length encoding, and *length* must
   be smaller than the default length.  When 0, the default length provided by
   the :class:`!InfoElement` in the :class:`!InfoModel` is used.

   Note that the values of *name* and *length* are only checked when the
   :class:`!InfoElementSpec` is added to a :class:`!Template`.  When an
   :class:`!InfoElementSpec` whose *length* is zero is added to a
   :class:`!Template`, the *length* of that :class:`!InfoElementSpec` is
   modified to reflect the default length of the :class:`!InfoElement`.

   Examples::

   >>> spec1 = pyfixbuf.InfoElementSpec("fooname")
   >>> spec2 = pyfixbuf.InfoElementSpec("sourceTransportPort")
   >>> spec3 = pyfixbuf.InfoElementSpec("flo_element", 4)

   .. attribute:: name : str

        The Information Element Specification name.

   .. attribute:: length : int

        The length override for the Information Element Specification.  A
        value of 0 indicates the length of the element is the default length
        specified for that :class:`InfoElement` in the :class:`InfoModel`.


Global Variables
===========================

pyfixbuf defines the following global constants:

.. data:: __version__

	The version of pyfixbuf.

.. data:: VARLEN

        The size used to indicate an :class:`~pyfxibuf.InfoElement` has a
	variable length.  (65535)

.. data:: CERT_PEN

        The private enterprise number assigned by IANA to the CERT division
	within the Software Engineering Institute.  (6871)

.. data:: BASICLIST

	An alias for :class:`~pyfixbuf.DataType`\ .BASIC_LIST.  The
	:meth:`Record.add_element` and :meth:`InfoModel.get_element_length`
	methods accept this value to help when constructing a :class:`Record`.

.. data:: SUBTEMPLATELIST

	An alias for :class:`~pyfixbuf.DataType`\ .SUB_TMPL_LIST.  The
	:meth:`Record.add_element` and :meth:`InfoModel.get_element_length`
	methods accept this value to help when constructing a :class:`Record`.

.. data:: SUBTEMPLATEMULTILIST

	An alias for :class:`~pyfixbuf.DataType`\ .SUB_TMPL_MULTI_LIST.  The
	:meth:`Record.add_element` and :meth:`InfoModel.get_element_length`
	methods accept this value to help when constructing a :class:`Record`.

..
  Local Variables:
  fill-column:78
  End:
