Implements DISPLAY-HINT parsing into base SNMP value

        Proper parsing seems impossible due to ambiguities.
        Here we are trying to do our best, but be prepared
        for failures on complicated DISPLAY-HINTs.

        Keep in mind that this parser only works with "text"
        input meaning `unicode` (Py2) or `str` (Py3).

def prettyIn(self, value):  # override asn1 type method
        """Implements DISPLAY-HINT parsing into base SNMP value

        Proper parsing seems impossible due to ambiguities.
        Here we are trying to do our best, but be prepared
        for failures on complicated DISPLAY-HINTs.

        Keep in mind that this parser only works with "text"
        input meaning `unicode` (Py2) or `str` (Py3).
        """
        for base in inspect.getmro(self.__class__):
            if not issubclass(base, TextualConvention) and issubclass(base, Asn1Item):
                break
        else:
            raise SmiError('TEXTUAL-CONVENTION has no underlying SNMP base type')

        if self.displayHint and (self.__integer.isSuperTypeOf(self, matchConstraints=False) and
                                 self.getNamedValues() or
                                 self.__unsigned32.isSuperTypeOf(self, matchConstraints=False) or
                                 self.__timeticks.isSuperTypeOf(self, matchConstraints=False)):
            value = str(value)

            _ = lambda t, f=0: (t, f)
            displayHintType, decimalPrecision = _(*self.displayHint.split('-'))
            if displayHintType == 'x' and (value.startswith('0x') or value.startswith('-0x')):
                try:
                    if value.startswith('-'):
                        return base.prettyIn(self, -int(value[3:], 16))
                    else:
                        return base.prettyIn(self, int(value[2:], 16))
                except Exception as exc:
                    raise SmiError(
                        'integer evaluation error: %s' % exc
                    )
            elif displayHintType == 'd':
                try:
                    return base.prettyIn(self, int(float(value) * 10**int(decimalPrecision)))
                except Exception as exc:
                    raise SmiError(
                        'float evaluation error: %s' % exc
                    )
            elif displayHintType == 'o' and (value.startswith('0') or value.startswith('-0')):
                try:
                    return base.prettyIn(self, int(value, 8))
                except Exception as exc:
                    raise SmiError(
                        'octal evaluation error: %s' % exc
                    )
            elif displayHintType == 'b' and (value.startswith('B') or value.startswith('-B')):
                negative = value.startswith('-')
                if negative:
                    value = value[2:]
                else:
                    value = value[1:]
                value = [x != '0' and 1 or 0 for x in value]
                binValue = 0
                while value:
                    binValue <<= value[0]
                    del value[0]
                return base.prettyIn(self, binValue)
            else:
                raise SmiError(
                    'Unsupported numeric type spec "%s" at %s' % (displayHintType, self.__class__.__name__)
                )

        elif self.displayHint and self.__octetString.isSuperTypeOf(self, matchConstraints=False):
            numBase = {
                'x': 16,
                'd': 10,
                'o': 8
            }
            numDigits = {
                'x': octets.str2octs(string.hexdigits),
                'o': octets.str2octs(string.octdigits),
                'd': octets.str2octs(string.digits)
            }

            # how do we know if object is initialized with display-hint
            # formatted text? based on "text" input maybe?
            # That boils down to `str` object on Py3 or `unicode` on Py2.
            if octets.isStringType(value) and not octets.isOctetsType(value):
                value = base.prettyIn(self, value)
            else:
                return base.prettyIn(self, value)

            outputValue = octets.str2octs('')
            runningValue = value
            displayHint = self.displayHint

            while runningValue and displayHint:
                # 1 this information is totally lost, just fail explicitly
                if displayHint[0] == '*':
                    raise SmiError(
                        'Can\'t parse "*" in DISPLAY-HINT (%s)' % self.__class__.__name__
                    )

                # 2 this becomes ambiguous when it comes to rendered value
                octetLength = ''
                while displayHint and displayHint[0] in string.digits:
                    octetLength += displayHint[0]
                    displayHint = displayHint[1:]

                # length is mandatory but people ignore that
                if not octetLength:
                    octetLength = len(runningValue)

                try:
                    octetLength = int(octetLength)
                except Exception:
                    raise SmiError(
                        'Bad octet length: %s' % octetLength
                    )

                if not displayHint:
                    raise SmiError(
                        'Short octet length: %s' % self.displayHint
                    )

                # 3
                displayFormat = displayHint[0]
                displayHint = displayHint[1:]

                # 4 this is the lifesaver -- we could use it as an anchor
                if displayHint and displayHint[0] not in string.digits and displayHint[0] != '*':
                    displaySep = displayHint[0]
                    displayHint = displayHint[1:]
                else:
                    displaySep = ''

                # 5 is probably impossible to support

                if displayFormat in ('a', 't'):
                    outputValue += runningValue[:octetLength]
                elif displayFormat in numBase:
                    if displaySep:
                        guessedOctetLength = runningValue.find(octets.str2octs(displaySep))
                        if guessedOctetLength == -1:
                            guessedOctetLength = len(runningValue)
                    else:
                        for idx in range(len(runningValue)):
                            if runningValue[idx] not in numDigits[displayFormat]:
                                guessedOctetLength = idx
                                break
                        else:
                            guessedOctetLength = len(runningValue)

                    try:
                        num = int(octets.octs2str(runningValue[:guessedOctetLength]), numBase[displayFormat])
                    except Exception as exc:
                        raise SmiError(
                            'Display format eval failure: %s: %s'
                            % (runningValue[:guessedOctetLength], exc)
                        )

                    num_as_bytes = []
                    if num:
                        while num:
                            num_as_bytes.append(num & 0xFF)
                            num >>= 8
                    else:
                        num_as_bytes = [0]

                    while len(num_as_bytes) < octetLength:
                        num_as_bytes.append(0)

                    num_as_bytes.reverse()

                    outputValue += octets.ints2octs(num_as_bytes)

                    if displaySep:
                        guessedOctetLength += 1

                    octetLength = guessedOctetLength
                else:
                    raise SmiError(
                        'Unsupported display format char: %s' %
                        displayFormat
                    )

                runningValue = runningValue[octetLength:]

                if not displayHint:
                    displayHint = self.displayHint

            return base.prettyIn(self, outputValue)

        else:
            return base.prettyIn(self, value)