/* * Copyright (c) 2025 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ use base64::alphabet; use base64::engine::general_purpose; use base64::engine::DecodePaddingMode; use base64::Engine; use cxx::CxxString; use std::pin::Pin; #[cxx::bridge(namespace = "webrtc")] mod ffi { #[repr(u8)] enum Base64DecodeSetting { Strict, Forgiving, } extern "Rust" { fn rs_base64_encode(data: &[u8]) -> String; fn rs_base64_decode( data: &[u8], options: Base64DecodeSetting, output: Pin<&mut CxxString>, ) -> bool; } } fn rs_base64_encode(data: &[u8]) -> String { general_purpose::STANDARD.encode(data) } const FORGIVING_ENGINE: general_purpose::GeneralPurpose = general_purpose::GeneralPurpose::new( &alphabet::STANDARD, general_purpose::GeneralPurposeConfig::new() .with_decode_padding_mode(DecodePaddingMode::Indifferent), ); fn rs_base64_decode( data: &[u8], options: ffi::Base64DecodeSetting, output: Pin<&mut CxxString>, ) -> bool { let result = match options { ffi::Base64DecodeSetting::Strict => general_purpose::STANDARD.decode(data), ffi::Base64DecodeSetting::Forgiving => { let data_without_whitespace: Vec = data.iter().filter(|&c| !c.is_ascii_whitespace()).copied().collect(); FORGIVING_ENGINE.decode(data_without_whitespace) } _ => unreachable!(), }; match result { Ok(vec) => { output.push_bytes(vec.as_slice()); true } Err(_) => false, } }