• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2024 Google LLC.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 use super::{upb_ExtensionRegistry, upb_MiniTable, Arena, RawArena, RawMessage};
9 
10 // LINT.IfChange(encode_status)
11 #[repr(C)]
12 #[derive(PartialEq, Eq, Copy, Clone, Debug)]
13 pub enum EncodeStatus {
14     Ok = 0,
15     OutOfMemory = 1,
16     MaxDepthExceeded = 2,
17     MissingRequired = 3,
18 }
19 // LINT.ThenChange()
20 
21 // LINT.IfChange(decode_status)
22 #[repr(C)]
23 #[derive(PartialEq, Eq, Copy, Clone, Debug)]
24 pub enum DecodeStatus {
25     Ok = 0,
26     Malformed = 1,
27     OutOfMemory = 2,
28     BadUtf8 = 3,
29     MaxDepthExceeded = 4,
30     MissingRequired = 5,
31     UnlinkedSubMessage = 6,
32 }
33 // LINT.ThenChange()
34 
35 #[repr(i32)]
36 #[allow(dead_code)]
37 enum DecodeOption {
38     AliasString = 1,
39     CheckRequired = 2,
40     ExperimentalAllowUnlinked = 4,
41     AlwaysValidateUtf8 = 8,
42 }
43 
44 /// If Err, then EncodeStatus != Ok.
45 ///
46 /// # Safety
47 /// - `msg` must be associated with `mini_table`.
encode( msg: RawMessage, mini_table: *const upb_MiniTable, ) -> Result<Vec<u8>, EncodeStatus>48 pub unsafe fn encode(
49     msg: RawMessage,
50     mini_table: *const upb_MiniTable,
51 ) -> Result<Vec<u8>, EncodeStatus> {
52     let arena = Arena::new();
53     let mut buf: *mut u8 = core::ptr::null_mut();
54     let mut len = 0usize;
55 
56     // SAFETY:
57     // - `mini_table` is the one associated with `msg`.
58     // - `buf` and `buf_size` are legally writable.
59     let status = unsafe { upb_Encode(msg, mini_table, 0, arena.raw(), &mut buf, &mut len) };
60 
61     if status == EncodeStatus::Ok {
62         assert!(!buf.is_null()); // EncodeStatus Ok should never return NULL data, even for len=0.
63         // SAFETY: upb guarantees that `buf` is valid to read for `len`.
64         Ok(unsafe { &*core::ptr::slice_from_raw_parts(buf, len) }.to_vec())
65     } else {
66         Err(status)
67     }
68 }
69 
70 /// Decodes into the provided message (merge semantics). If Err, then
71 /// DecodeStatus != Ok.
72 ///
73 /// # Safety
74 /// - `msg` must be mutable.
75 /// - `msg` must be associated with `mini_table`.
decode( buf: &[u8], msg: RawMessage, mini_table: *const upb_MiniTable, arena: &Arena, ) -> Result<(), DecodeStatus>76 pub unsafe fn decode(
77     buf: &[u8],
78     msg: RawMessage,
79     mini_table: *const upb_MiniTable,
80     arena: &Arena,
81 ) -> Result<(), DecodeStatus> {
82     let len = buf.len();
83     let buf = buf.as_ptr();
84     let options = DecodeOption::CheckRequired as i32;
85 
86     // SAFETY:
87     // - `mini_table` is the one associated with `msg`
88     // - `buf` is legally readable for at least `buf_size` bytes.
89     // - `extreg` is null.
90     let status =
91         unsafe { upb_Decode(buf, len, msg, mini_table, core::ptr::null(), options, arena.raw()) };
92     match status {
93         DecodeStatus::Ok => Ok(()),
94         _ => Err(status),
95     }
96 }
97 
98 extern "C" {
99     // SAFETY:
100     // - `mini_table` is the one associated with `msg`
101     // - `buf` and `buf_size` are legally writable.
upb_Encode( msg: RawMessage, mini_table: *const upb_MiniTable, options: i32, arena: RawArena, buf: *mut *mut u8, buf_size: *mut usize, ) -> EncodeStatus102     pub fn upb_Encode(
103         msg: RawMessage,
104         mini_table: *const upb_MiniTable,
105         options: i32,
106         arena: RawArena,
107         buf: *mut *mut u8,
108         buf_size: *mut usize,
109     ) -> EncodeStatus;
110 
111     // SAFETY:
112     // - `mini_table` is the one associated with `msg`
113     // - `buf` is legally readable for at least `buf_size` bytes.
114     // - `extreg` is either null or points at a valid upb_ExtensionRegistry.
upb_Decode( buf: *const u8, buf_size: usize, msg: RawMessage, mini_table: *const upb_MiniTable, extreg: *const upb_ExtensionRegistry, options: i32, arena: RawArena, ) -> DecodeStatus115     pub fn upb_Decode(
116         buf: *const u8,
117         buf_size: usize,
118         msg: RawMessage,
119         mini_table: *const upb_MiniTable,
120         extreg: *const upb_ExtensionRegistry,
121         options: i32,
122         arena: RawArena,
123     ) -> DecodeStatus;
124 }
125 
126 #[cfg(test)]
127 mod tests {
128     use super::*;
129     use googletest::gtest;
130 
131     #[gtest]
assert_wire_linked()132     fn assert_wire_linked() {
133         use crate::assert_linked;
134         assert_linked!(upb_Encode);
135         assert_linked!(upb_Decode);
136     }
137 }
138