Skip to main content

codec_multibase/
encode.rs

1// SPDX-FileCopyrightText: 2026 ReallyMe LLC
2//
3// SPDX-License-Identifier: MIT OR Apache-2.0
4
5use base64::{encoded_len, engine::general_purpose::URL_SAFE_NO_PAD, Engine as _};
6use zeroize::Zeroizing;
7
8use crate::{Base58Error, MultibaseError, MAX_BASE58BTC_DECODED_LEN};
9
10const MULTIBASE_BASE58BTC_PREFIX: u8 = b'z';
11const MULTIBASE_BASE64URL_PREFIX: u8 = b'u';
12
13/// Encode bytes using multibase base58btc with the `z` prefix.
14pub fn bytes_to_multibase58btc(bytes: &[u8]) -> Result<String, Base58Error> {
15    if bytes.len() > MAX_BASE58BTC_DECODED_LEN {
16        return Err(Base58Error::InputTooLarge);
17    }
18    let mut output = Zeroizing::new(Vec::with_capacity(1));
19    output.push(MULTIBASE_BASE58BTC_PREFIX);
20    bs58::encode(bytes)
21        .onto(&mut *output)
22        .map_err(|_| Base58Error::BufferTooSmall)?;
23    match String::from_utf8(core::mem::take(&mut *output)) {
24        Ok(encoded) => Ok(encoded),
25        Err(error) => {
26            let _bytes = Zeroizing::new(error.into_bytes());
27            Err(Base58Error::DecodeFailed)
28        }
29    }
30}
31
32/// Encode bytes using multibase base64url with the `u` prefix.
33pub fn bytes_to_multibase_base64url(bytes: &[u8]) -> Result<String, MultibaseError> {
34    let encoded_length = encoded_len(bytes.len(), false).ok_or(MultibaseError::LengthOverflow)?;
35    let output_length = encoded_length
36        .checked_add(1)
37        .ok_or(MultibaseError::LengthOverflow)?;
38    let mut output = Zeroizing::new(vec![0_u8; output_length]);
39    output[0] = MULTIBASE_BASE64URL_PREFIX;
40    let written = URL_SAFE_NO_PAD
41        .encode_slice(bytes, &mut output[1..])
42        .map_err(|_| MultibaseError::LengthOverflow)?;
43    if written != encoded_length {
44        return Err(MultibaseError::LengthOverflow);
45    }
46    match String::from_utf8(core::mem::take(&mut *output)) {
47        Ok(encoded) => Ok(encoded),
48        Err(error) => {
49            let _bytes = Zeroizing::new(error.into_bytes());
50            Err(MultibaseError::LengthOverflow)
51        }
52    }
53}