Skip to content

Encoder class only accepts encoding names, not prefix characters #39

Description

@sumanjeet0012

The Encoder class only accepts encoding name strings (e.g., "base16"). go-multibase's EncoderByName() accepts both names and single-character prefix codes (e.g., "f" for base16), making it more flexible for CLI tools and config-driven encoding.

Problem

Current Python Encoder:

class Encoder:
    def __init__(self, encoding):
        if encoding not in ENCODINGS_LOOKUP:
            raise UnsupportedEncodingError(...)
        self.encoding = encoding
        self._codec = ENCODINGS_LOOKUP[encoding]

This only works with name strings:

Encoder("base16")   # ✅ Works
Encoder("f")        # ❌ Raises UnsupportedEncodingError
Encoder(b"f")       # ❌ Raises UnsupportedEncodingError

Go's EncoderByName() accepts both:

// Go: both work
enc1, _ := EncoderByName("base16")  // by name
enc2, _ := EncoderByName("f")       // by single-char prefix

The implementation checks if the string is a single Unicode rune and treats it as a prefix code:

func EncoderByName(str string) (Encoder, error) {
    if utf8.RuneCountInString(str) == 1 {
        r, _ := utf8.DecodeRuneInString(str)
        base = Encoding(r)  // treat as prefix code
    } else {
        base = Encodings[str]  // treat as name
    }
}

Proposed Solution

Add an encoder_by_name() factory function (keeping Encoder.__init__ unchanged for backward compatibility):

def encoder_by_name(name_or_prefix: str) -> Encoder:
    """Create an Encoder from a name or single-character prefix.

    >>> encoder_by_name("base16")  # by name
    >>> encoder_by_name("f")       # by prefix character
    >>> encoder_by_name("🚀")      # by emoji prefix (base256emoji)
    """
    # Try as name first
    if name_or_prefix in ENCODINGS_LOOKUP:
        return Encoder(name_or_prefix)

    # Try as single-character prefix
    prefix_bytes = name_or_prefix.encode("utf-8")
    if prefix_bytes in ENCODINGS_LOOKUP:
        codec = ENCODINGS_LOOKUP[prefix_bytes]
        return Encoder(codec.encoding)

    raise UnsupportedEncodingError(
        f"Encoding {name_or_prefix!r} not supported."
    )

Export from __init__.py and add tests.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions