// 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

mod sys {
    pub use super::super::super::*;
}

use sys::mem::arena::RawArena;
use sys::message::message::RawMessage;
use sys::mini_table::extension_registry::upb_ExtensionRegistry;
use sys::mini_table::mini_table::RawMiniTable;

// LINT.IfChange(encode_status)
#[repr(C)]
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
#[allow(unused)] // C struct values used in FFI.
pub enum EncodeStatus {
    Ok = 0,
    OutOfMemory = 1,
    MaxDepthExceeded = 3,
    MissingRequired = 10,
    MaxSizeExceeded = 11,
}
// LINT.ThenChange()

// LINT.IfChange(decode_status)
#[repr(C)]
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
#[allow(unused)] // C struct values used in FFI.
pub enum DecodeStatus {
    Ok = 0,
    OutOfMemory = 1,
    Malformed = 2,
    MaxDepthExceeded = 3,
    BadUtf8 = 10,
    MissingRequired = 11,
}
// LINT.ThenChange()

unsafe extern "C" {
    // SAFETY:
    // - `mini_table` is the one associated with `msg`
    // - `msg` is legal to dereference and read from.
    // - `buf` and `buf_size` are legally writable.
    pub fn upb_Encode(
        msg: RawMessage,
        mini_table: RawMiniTable,
        options: i32,
        arena: RawArena,
        buf: *mut *mut u8,
        buf_size: *mut usize,
    ) -> EncodeStatus;

    // SAFETY:
    // - `mini_table` is the one associated with `msg`
    // - `msg` is legal to dereference and read from.
    // - `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: RawMiniTable,
        extreg: *const upb_ExtensionRegistry,
        options: i32,
        arena: RawArena,
    ) -> DecodeStatus;

    // SAFETY:
    // - `msg` is legal to dereference and read from.
    // - `mini_table` is the one associated with `msg`.
    pub fn upb_ByteSize(msg: RawMessage, mini_table: RawMiniTable) -> usize;
}

#[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);
        assert_linked!(upb_ByteSize);
    }
}
