# Path: habitat/parser.py
# class ParserModule(object):
#     """
#     Base class for real ParserModules to inherit from.
# 
#     **ParserModules** are classes which turn radio strings into useful data.
#     They do not have to inherit from :class:`ParserModule`, but can if they
#     want. They must implement :meth:`pre_parse` and :meth:`parse` as described
#     below.
#     """
#     def __init__(self, parser):
#         self.parser = parser
#         self.loadable_manager = parser.loadable_manager
# 
#     def pre_parse(self, string):
#         """
#         Go though *string* and attempt to extract a callsign, returning
#         it as a string. If *string* is not parseable by this module, raise
#         :py:class:`CantParse`. If *string* might be parseable but no callsign
#         could be extracted, raise :py:class:`CantExtractCallsign`.
#         """
#         raise ValueError()
# 
#     def parse(self, string, config):
#         """
#         Go through *string* which has been identified as the format this
#         parser module should be able to parse, extracting the data as per
#         the information in *config*, which is the ``sentence`` dictionary
#         extracted from the payload's configuration document.
#         """
#         raise ValueError()
# 
# class CantParse(Exception):
#     """Parser module cannot parse the given sentence."""
#     pass
# 
# Path: habitat/utils/checksums.py
# def crc16_ccitt(data):
# def xor(data):
# def fletcher_16(data, modulus=255):


import re
from ..parser import ParserModule, CantParse
from ..utils import checksums
                raise ValueError("Specified checksum algorithm is invalid.")
            if len(config["fields"]) < 1:
                raise ValueError("No fields are defined.")
            for field in config["fields"]:
                field["name"]
                field["sensor"]
                if field["name"][0] == "_":
                    raise ValueError("Field name starts with an underscore.")
                field_names.append(field["name"])
            if len(field_names) != len(set(field_names)):
                raise ValueError("Duplicate field name.")
        except (KeyError, TypeError):
            raise ValueError("Invalid configuration document.")

    def _verify_checksum(self, string, checksum, algorithm):
        """
        Verifies *string*'s checksum.

        Computes the checksum defined by *algorithm* over *string*
        and compares it to that given in *checksum*.
        Raises :py:exc:`ValueError <exceptions.ValueError>`
        on discrepancy.
        """

        if checksum == None and algorithm != "none":
            raise ValueError("No checksum found but config specifies one.")
        elif algorithm == "crc16-ccitt":
            if checksums.crc16_ccitt(string) != checksum.upper():
                raise ValueError("Invalid CRC16-CCITT checksum.")
        elif algorithm == "xor":

# Path: habitat/parser.py
# class ParserModule(object):
#     """
#     Base class for real ParserModules to inherit from.
# 
#     **ParserModules** are classes which turn radio strings into useful data.
#     They do not have to inherit from :class:`ParserModule`, but can if they
#     want. They must implement :meth:`pre_parse` and :meth:`parse` as described
#     below.
#     """
#     def __init__(self, parser):
#         self.parser = parser
#         self.loadable_manager = parser.loadable_manager
# 
#     def pre_parse(self, string):
#         """
#         Go though *string* and attempt to extract a callsign, returning
#         it as a string. If *string* is not parseable by this module, raise
#         :py:class:`CantParse`. If *string* might be parseable but no callsign
#         could be extracted, raise :py:class:`CantExtractCallsign`.
#         """
#         raise ValueError()
# 
#     def parse(self, string, config):
#         """
#         Go through *string* which has been identified as the format this
#         parser module should be able to parse, extracting the data as per
#         the information in *config*, which is the ``sentence`` dictionary
#         extracted from the payload's configuration document.
#         """
#         raise ValueError()
# 
# class CantParse(Exception):
#     """Parser module cannot parse the given sentence."""
#     pass
# 
# Path: habitat/utils/checksums.py
# def crc16_ccitt(data):
# def xor(data):
# def fletcher_16(data, modulus=255):


# Path: habitat/parser_modules/ukhas_parser.py
import re
from ..parser import ParserModule, CantParse
from ..utils import checksums

                raise ValueError("Specified checksum algorithm is invalid.")
            if len(config["fields"]) < 1:
                raise ValueError("No fields are defined.")
            for field in config["fields"]:
                field["name"]
                field["sensor"]
                if field["name"][0] == "_":
                    raise ValueError("Field name starts with an underscore.")
                field_names.append(field["name"])
            if len(field_names) != len(set(field_names)):
                raise ValueError("Duplicate field name.")
        except (KeyError, TypeError):
            raise ValueError("Invalid configuration document.")

    def _verify_checksum(self, string, checksum, algorithm):
        """
        Verifies *string*'s checksum.

        Computes the checksum defined by *algorithm* over *string*
        and compares it to that given in *checksum*.
        Raises :py:exc:`ValueError <exceptions.ValueError>`
        on discrepancy.
        """

        if checksum == None and algorithm != "none":
            raise ValueError("No checksum found but config specifies one.")
        elif algorithm == "crc16-ccitt":
            if checksums.crc16_ccitt(string) != checksum.upper():
                raise ValueError("Invalid CRC16-CCITT checksum.")
        elif algorithm == "xor":

            if checksums.xor(string) != checksum.upper():