Protocol Buffers - Google's data interchange format (grpc依赖)
https://developers.google.com/protocol-buffers/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
137 lines
3.7 KiB
137 lines
3.7 KiB
// Protocol Buffers - Google's data interchange format |
|
// Copyright 2024 Google LLC. All rights reserved. |
|
// |
|
// Use of this source code is governed by a BSD-style |
|
// license that can be found in the LICENSE file or at |
|
// https://developers.google.com/open-source/licenses/bsd |
|
|
|
use super::{upb_ExtensionRegistry, upb_MiniTable, Arena, RawArena, RawMessage}; |
|
|
|
// LINT.IfChange(encode_status) |
|
#[repr(C)] |
|
#[derive(PartialEq, Eq, Copy, Clone, Debug)] |
|
pub enum EncodeStatus { |
|
Ok = 0, |
|
OutOfMemory = 1, |
|
MaxDepthExceeded = 2, |
|
MissingRequired = 3, |
|
} |
|
// LINT.ThenChange() |
|
|
|
// LINT.IfChange(decode_status) |
|
#[repr(C)] |
|
#[derive(PartialEq, Eq, Copy, Clone, Debug)] |
|
pub enum DecodeStatus { |
|
Ok = 0, |
|
Malformed = 1, |
|
OutOfMemory = 2, |
|
BadUtf8 = 3, |
|
MaxDepthExceeded = 4, |
|
MissingRequired = 5, |
|
UnlinkedSubMessage = 6, |
|
} |
|
// LINT.ThenChange() |
|
|
|
#[repr(i32)] |
|
#[allow(dead_code)] |
|
enum DecodeOption { |
|
AliasString = 1, |
|
CheckRequired = 2, |
|
ExperimentalAllowUnlinked = 4, |
|
AlwaysValidateUtf8 = 8, |
|
} |
|
|
|
/// If Err, then EncodeStatus != Ok. |
|
/// |
|
/// # Safety |
|
/// - `msg` must be associated with `mini_table`. |
|
pub unsafe fn encode( |
|
msg: RawMessage, |
|
mini_table: *const upb_MiniTable, |
|
) -> Result<Vec<u8>, EncodeStatus> { |
|
let arena = Arena::new(); |
|
let mut buf: *mut u8 = core::ptr::null_mut(); |
|
let mut len = 0usize; |
|
|
|
// SAFETY: |
|
// - `mini_table` is the one associated with `msg`. |
|
// - `buf` and `buf_size` are legally writable. |
|
let status = unsafe { upb_Encode(msg, mini_table, 0, arena.raw(), &mut buf, &mut len) }; |
|
|
|
if status == EncodeStatus::Ok { |
|
assert!(!buf.is_null()); // EncodeStatus Ok should never return NULL data, even for len=0. |
|
// SAFETY: upb guarantees that `buf` is valid to read for `len`. |
|
Ok(unsafe { &*core::ptr::slice_from_raw_parts(buf, len) }.to_vec()) |
|
} else { |
|
Err(status) |
|
} |
|
} |
|
|
|
/// Decodes into the provided message (merge semantics). If Err, then |
|
/// DecodeStatus != Ok. |
|
/// |
|
/// # Safety |
|
/// - `msg` must be mutable. |
|
/// - `msg` must be associated with `mini_table`. |
|
pub unsafe fn decode( |
|
buf: &[u8], |
|
msg: RawMessage, |
|
mini_table: *const upb_MiniTable, |
|
arena: &Arena, |
|
) -> Result<(), DecodeStatus> { |
|
let len = buf.len(); |
|
let buf = buf.as_ptr(); |
|
let options = DecodeOption::CheckRequired as i32; |
|
|
|
// SAFETY: |
|
// - `mini_table` is the one associated with `msg` |
|
// - `buf` is legally readable for at least `buf_size` bytes. |
|
// - `extreg` is null. |
|
let status = |
|
unsafe { upb_Decode(buf, len, msg, mini_table, core::ptr::null(), options, arena.raw()) }; |
|
match status { |
|
DecodeStatus::Ok => Ok(()), |
|
_ => Err(status), |
|
} |
|
} |
|
|
|
extern "C" { |
|
// SAFETY: |
|
// - `mini_table` is the one associated with `msg` |
|
// - `buf` and `buf_size` are legally writable. |
|
pub fn upb_Encode( |
|
msg: RawMessage, |
|
mini_table: *const upb_MiniTable, |
|
options: i32, |
|
arena: RawArena, |
|
buf: *mut *mut u8, |
|
buf_size: *mut usize, |
|
) -> EncodeStatus; |
|
|
|
// SAFETY: |
|
// - `mini_table` is the one associated with `msg` |
|
// - `buf` is legally readable for at least `buf_size` bytes. |
|
// - `extreg` is either null or points at a valid upb_ExtensionRegistry. |
|
pub fn upb_Decode( |
|
buf: *const u8, |
|
buf_size: usize, |
|
msg: RawMessage, |
|
mini_table: *const upb_MiniTable, |
|
extreg: *const upb_ExtensionRegistry, |
|
options: i32, |
|
arena: RawArena, |
|
) -> DecodeStatus; |
|
} |
|
|
|
#[cfg(test)] |
|
mod tests { |
|
use super::*; |
|
use googletest::gtest; |
|
|
|
#[gtest] |
|
fn assert_wire_linked() { |
|
use crate::assert_linked; |
|
assert_linked!(upb_Encode); |
|
assert_linked!(upb_Decode); |
|
} |
|
}
|
|
|