diff --git a/kitty/data-types.c b/kitty/data-types.c index 65bf57ce3..fbf8308ab 100644 --- a/kitty/data-types.c +++ b/kitty/data-types.c @@ -89,6 +89,17 @@ pybase64_encode(PyObject UNUSED *self, PyObject *args) { return ans; } +static PyObject* +base64_encode_into(PyObject UNUSED *self, PyObject *args) { + int add_padding = 0; + RAII_PY_BUFFER(view); RAII_PY_BUFFER(output); + if (!PyArg_ParseTuple(args, "s*w*|i", &view, &add_padding)) return NULL; + size_t sz = required_buffer_size_for_base64_encode(view.len); + if (output.len < (ssize_t)sz) { PyErr_SetString(PyExc_TypeError, "output buffer too small"); return NULL; } + base64_encode8(view.buf, view.len, output.buf, &sz, add_padding); + return PyLong_FromSize_t(sz); +} + static PyObject* pybase64_decode(PyObject UNUSED *self, PyObject *args) { RAII_PY_BUFFER(view); @@ -105,6 +116,20 @@ pybase64_decode(PyObject UNUSED *self, PyObject *args) { return ans; } +static PyObject* +base64_decode_into(PyObject UNUSED *self, PyObject *args) { + RAII_PY_BUFFER(view); RAII_PY_BUFFER(output); + if (!PyArg_ParseTuple(args, "s*", &view, &output)) return NULL; + size_t sz = required_buffer_size_for_base64_decode(view.len); + if (output.len < (ssize_t)sz) { PyErr_SetString(PyExc_TypeError, "output buffer too small"); return NULL; } + if (!base64_decode8(view.buf, view.len, output.buf, &sz)) { + PyErr_SetString(PyExc_ValueError, "Invalid base64 input data"); + return NULL; + } + return PyLong_FromSize_t(sz); +} + + typedef struct StreamingBase64Decoder { PyObject_HEAD struct base64_state state; @@ -560,7 +585,9 @@ static PyMethodDef module_methods[] = { {"close_tty", close_tty, METH_VARARGS, ""}, {"set_iutf8_fd", (PyCFunction)pyset_iutf8, METH_VARARGS, ""}, {"base64_encode", (PyCFunction)pybase64_encode, METH_VARARGS, ""}, + {"base64_encode_into", (PyCFunction)base64_encode_into, METH_VARARGS, ""}, {"base64_decode", (PyCFunction)pybase64_decode, METH_VARARGS, ""}, + {"base64_decode_into", (PyCFunction)base64_decode_into, METH_VARARGS, ""}, {"thread_write", (PyCFunction)cm_thread_write, METH_VARARGS, ""}, {"redirect_std_streams", (PyCFunction)redirect_std_streams, METH_VARARGS, ""}, {"locale_is_valid", (PyCFunction)locale_is_valid, METH_VARARGS, ""}, diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index bfd5c7e19..954995878 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -1682,8 +1682,10 @@ def expand_ansi_c_escapes(test: str) -> str: ... def update_tab_bar_edge_colors(os_window_id: int) -> bool: ... def mask_kitty_signals_process_wide() -> None: ... def is_modifier_key(key: int) -> bool: ... -def base64_encode(src: Union[bytes,str], add_padding: bool = False) -> bytes: ... -def base64_decode(src: Union[bytes,str]) -> bytes: ... +def base64_encode(src: ReadableBuffer, add_padding: bool = False) -> bytes: ... +def base64_encode_into(src: ReadableBuffer, output: WriteableBuffer, add_padding: bool = False) -> int: ... +def base64_decode(src: ReadableBuffer) -> bytes: ... +def base64_decode_into(src: ReadableBuffer, output: WriteableBuffer) -> int: ... def cocoa_recreate_global_menu() -> None: ... def cocoa_clear_global_shortcuts() -> None: ... def update_pointer_shape(os_window_id: int) -> None: ...