1
Fork 0
mirror of https://github.com/RGBCube/DML synced 2025-07-27 23:57:44 +00:00
DML/dml/encoder.py
2022-03-19 22:15:26 +03:00

61 lines
2.1 KiB
Python

import typing as t
from .errors import DecodeError
from .symbols import symbols as s
__all__ = ("encode", "decode")
def encode(text: t.Union[t.Generator, t.List[str], str], *, out: str = None) -> t.Optional[t.Generator[str, None, None]]:
"""Encodes text into Dotted Markup Language (DML)
Arguments:
text (Union[Generator, List[str], str]): The text to encode.
out (str): The filepath to write the encoded file to. If not specified, the encoded text will be returned as a generator.
Returns:
Optional[Generator[str, None, None]]: The encoded text as a generator.
"""
def inner() -> t.Generator[str, None, None]:
for char_ in text:
yield format(ord(char_), "b").replace("0", s["0"]).replace("1", s["1"]) + s["stop"]
if out:
out = out + ".dml" if not out.endswith(".dml") else out
with open(out, "w") as f:
for char in inner():
f.write(char)
else:
return inner()
def decode(text: t.Union[t.Generator, t.List[str], str], *, out: str = None) -> t.Optional[t.Generator[str, None, None]]:
"""Decodes text from Dotted Markup Language (DML)
Arguments:
text (Union[Generator, List[str], str]): The text to decode.
out (str): The filepath to write the decoded file to. If not specified, the decoded text will be returned as a generator.
Returns:
Optional[Generator[str, None, None]]: The decoded text as a generator.
Raises:
DecodeError: If the text is not valid DML.
"""
def inner() -> t.Generator[str, None, None]:
nonlocal text
if isinstance(text, str):
text = [e + s["stop"] for e in text.split(s["stop"]) if e]
for char_ in text:
if any(e not in s.values() for e in char_):
raise DecodeError(f"Invalid character: '{char_}', expected {s['1']}, {s['0']} or {s['stop']}")
yield chr(int(char_[:-1].replace(s['0'], "0").replace(s['1'], "1"), 2))
if out:
with open(out, "w") as f:
for char in inner():
f.write(char)
else:
return inner()