codec_multibase/decode.rs
1// SPDX-FileCopyrightText: 2026 ReallyMe LLC
2//
3// SPDX-License-Identifier: MIT OR Apache-2.0
4
5use codec_base64url::base64url_to_bytes;
6
7use crate::{base58btc_decode, MultibaseError};
8
9/// Decode a supported multibase string to raw bytes.
10///
11/// The multibase prefix is the first Unicode scalar value, which may be
12/// more than one byte. We therefore split on a character boundary via the
13/// char iterator rather than a byte index: slicing at byte 1 would panic
14/// on any input whose first character is multi-byte (e.g. `"é"`), and this
15/// function is reached with untrusted input through
16/// [`parse_multikey`](../../multikey/index.html).
17pub fn multibase_to_bytes(multibase: &str) -> Result<Vec<u8>, MultibaseError> {
18 const MAX_MULTIBASE_INPUT_LEN: usize = codec_base64url::MAX_BASE64URL_INPUT_LEN + 1;
19 if multibase.len() > MAX_MULTIBASE_INPUT_LEN {
20 return Err(MultibaseError::InputTooLarge);
21 }
22 let mut chars = multibase.chars();
23 let prefix = chars.next().ok_or(MultibaseError::TooShort)?;
24 // The remainder of the string after the prefix character.
25 let data = chars.as_str();
26 match prefix {
27 'z' => Ok(base58btc_decode(data)?),
28 'u' => base64url_to_bytes(data).map_err(|_| MultibaseError::Base64Url),
29 _ => Err(MultibaseError::UnsupportedPrefix),
30 }
31}