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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions