// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#![allow(dead_code)]
#![allow(unused_imports)]

use crate::ipc::gen::Schema::*;
use flatbuffers::EndianScalar;
use std::{cmp::Ordering, mem};
// automatically generated by the FlatBuffers compiler, do not modify

// struct Block, aligned to 8
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq)]
pub struct Block(pub [u8; 24]);
impl std::fmt::Debug for Block {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.debug_struct("Block")
            .field("offset", &self.offset())
            .field("metaDataLength", &self.metaDataLength())
            .field("bodyLength", &self.bodyLength())
            .finish()
    }
}

impl flatbuffers::SimpleToVerifyInSlice for Block {}
impl flatbuffers::SafeSliceAccess for Block {}
impl<'a> flatbuffers::Follow<'a> for Block {
    type Inner = &'a Block;
    #[inline]
    fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
        <&'a Block>::follow(buf, loc)
    }
}
impl<'a> flatbuffers::Follow<'a> for &'a Block {
    type Inner = &'a Block;
    #[inline]
    fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
        flatbuffers::follow_cast_ref::<Block>(buf, loc)
    }
}
impl<'b> flatbuffers::Push for Block {
    type Output = Block;
    #[inline]
    fn push(&self, dst: &mut [u8], _rest: &[u8]) {
        let src = unsafe {
            ::std::slice::from_raw_parts(self as *const Block as *const u8, Self::size())
        };
        dst.copy_from_slice(src);
    }
}
impl<'b> flatbuffers::Push for &'b Block {
    type Output = Block;

    #[inline]
    fn push(&self, dst: &mut [u8], _rest: &[u8]) {
        let src = unsafe {
            ::std::slice::from_raw_parts(*self as *const Block as *const u8, Self::size())
        };
        dst.copy_from_slice(src);
    }
}

impl<'a> flatbuffers::Verifiable for Block {
    #[inline]
    fn run_verifier(
        v: &mut flatbuffers::Verifier,
        pos: usize,
    ) -> Result<(), flatbuffers::InvalidFlatbuffer> {
        use flatbuffers::Verifiable;
        v.in_buffer::<Self>(pos)
    }
}
impl Block {
    #[allow(clippy::too_many_arguments)]
    pub fn new(offset: i64, metaDataLength: i32, bodyLength: i64) -> Self {
        let mut s = Self([0; 24]);
        s.set_offset(offset);
        s.set_metaDataLength(metaDataLength);
        s.set_bodyLength(bodyLength);
        s
    }

    /// Index to the start of the RecordBlock (note this is past the Message header)
    pub fn offset(&self) -> i64 {
        let mut mem = core::mem::MaybeUninit::<i64>::uninit();
        unsafe {
            core::ptr::copy_nonoverlapping(
                self.0[0..].as_ptr(),
                mem.as_mut_ptr() as *mut u8,
                core::mem::size_of::<i64>(),
            );
            mem.assume_init()
        }
        .from_little_endian()
    }

    pub fn set_offset(&mut self, x: i64) {
        let x_le = x.to_little_endian();
        unsafe {
            core::ptr::copy_nonoverlapping(
                &x_le as *const i64 as *const u8,
                self.0[0..].as_mut_ptr(),
                core::mem::size_of::<i64>(),
            );
        }
    }

    /// Length of the metadata
    pub fn metaDataLength(&self) -> i32 {
        let mut mem = core::mem::MaybeUninit::<i32>::uninit();
        unsafe {
            core::ptr::copy_nonoverlapping(
                self.0[8..].as_ptr(),
                mem.as_mut_ptr() as *mut u8,
                core::mem::size_of::<i32>(),
            );
            mem.assume_init()
        }
        .from_little_endian()
    }

    pub fn set_metaDataLength(&mut self, x: i32) {
        let x_le = x.to_little_endian();
        unsafe {
            core::ptr::copy_nonoverlapping(
                &x_le as *const i32 as *const u8,
                self.0[8..].as_mut_ptr(),
                core::mem::size_of::<i32>(),
            );
        }
    }

    /// Length of the data (this is aligned so there can be a gap between this and
    /// the metadata).
    pub fn bodyLength(&self) -> i64 {
        let mut mem = core::mem::MaybeUninit::<i64>::uninit();
        unsafe {
            core::ptr::copy_nonoverlapping(
                self.0[16..].as_ptr(),
                mem.as_mut_ptr() as *mut u8,
                core::mem::size_of::<i64>(),
            );
            mem.assume_init()
        }
        .from_little_endian()
    }

    pub fn set_bodyLength(&mut self, x: i64) {
        let x_le = x.to_little_endian();
        unsafe {
            core::ptr::copy_nonoverlapping(
                &x_le as *const i64 as *const u8,
                self.0[16..].as_mut_ptr(),
                core::mem::size_of::<i64>(),
            );
        }
    }
}

pub enum FooterOffset {}
#[derive(Copy, Clone, PartialEq)]

/// ----------------------------------------------------------------------
/// Arrow File metadata
///
pub struct Footer<'a> {
    pub _tab: flatbuffers::Table<'a>,
}

impl<'a> flatbuffers::Follow<'a> for Footer<'a> {
    type Inner = Footer<'a>;
    #[inline]
    fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
        Self {
            _tab: flatbuffers::Table { buf, loc },
        }
    }
}

impl<'a> Footer<'a> {
    #[inline]
    pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
        Footer { _tab: table }
    }
    #[allow(unused_mut)]
    pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(
        _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>,
        args: &'args FooterArgs<'args>,
    ) -> flatbuffers::WIPOffset<Footer<'bldr>> {
        let mut builder = FooterBuilder::new(_fbb);
        if let Some(x) = args.custom_metadata {
            builder.add_custom_metadata(x);
        }
        if let Some(x) = args.recordBatches {
            builder.add_recordBatches(x);
        }
        if let Some(x) = args.dictionaries {
            builder.add_dictionaries(x);
        }
        if let Some(x) = args.schema {
            builder.add_schema(x);
        }
        builder.add_version(args.version);
        builder.finish()
    }

    pub const VT_VERSION: flatbuffers::VOffsetT = 4;
    pub const VT_SCHEMA: flatbuffers::VOffsetT = 6;
    pub const VT_DICTIONARIES: flatbuffers::VOffsetT = 8;
    pub const VT_RECORDBATCHES: flatbuffers::VOffsetT = 10;
    pub const VT_CUSTOM_METADATA: flatbuffers::VOffsetT = 12;

    #[inline]
    pub fn version(&self) -> MetadataVersion {
        self._tab
            .get::<MetadataVersion>(Footer::VT_VERSION, Some(MetadataVersion::V1))
            .unwrap()
    }
    #[inline]
    pub fn schema(&self) -> Option<Schema<'a>> {
        self._tab
            .get::<flatbuffers::ForwardsUOffset<Schema>>(Footer::VT_SCHEMA, None)
    }
    #[inline]
    pub fn dictionaries(&self) -> Option<&'a [Block]> {
        self._tab
            .get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, Block>>>(
                Footer::VT_DICTIONARIES,
                None,
            )
            .map(|v| v.safe_slice())
    }
    #[inline]
    pub fn recordBatches(&self) -> Option<&'a [Block]> {
        self._tab
            .get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, Block>>>(
                Footer::VT_RECORDBATCHES,
                None,
            )
            .map(|v| v.safe_slice())
    }
    /// User-defined metadata
    #[inline]
    pub fn custom_metadata(
        &self,
    ) -> Option<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<KeyValue<'a>>>> {
        self._tab.get::<flatbuffers::ForwardsUOffset<
            flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<KeyValue>>,
        >>(Footer::VT_CUSTOM_METADATA, None)
    }
}

impl flatbuffers::Verifiable for Footer<'_> {
    #[inline]
    fn run_verifier(
        v: &mut flatbuffers::Verifier,
        pos: usize,
    ) -> Result<(), flatbuffers::InvalidFlatbuffer> {
        use flatbuffers::Verifiable;
        v.visit_table(pos)?
            .visit_field::<MetadataVersion>(&"version", Self::VT_VERSION, false)?
            .visit_field::<flatbuffers::ForwardsUOffset<Schema>>(
                &"schema",
                Self::VT_SCHEMA,
                false,
            )?
            .visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, Block>>>(
                &"dictionaries",
                Self::VT_DICTIONARIES,
                false,
            )?
            .visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, Block>>>(
                &"recordBatches",
                Self::VT_RECORDBATCHES,
                false,
            )?
            .visit_field::<flatbuffers::ForwardsUOffset<
                flatbuffers::Vector<'_, flatbuffers::ForwardsUOffset<KeyValue>>,
            >>(&"custom_metadata", Self::VT_CUSTOM_METADATA, false)?
            .finish();
        Ok(())
    }
}
pub struct FooterArgs<'a> {
    pub version: MetadataVersion,
    pub schema: Option<flatbuffers::WIPOffset<Schema<'a>>>,
    pub dictionaries: Option<flatbuffers::WIPOffset<flatbuffers::Vector<'a, Block>>>,
    pub recordBatches: Option<flatbuffers::WIPOffset<flatbuffers::Vector<'a, Block>>>,
    pub custom_metadata: Option<
        flatbuffers::WIPOffset<
            flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<KeyValue<'a>>>,
        >,
    >,
}
impl<'a> Default for FooterArgs<'a> {
    #[inline]
    fn default() -> Self {
        FooterArgs {
            version: MetadataVersion::V1,
            schema: None,
            dictionaries: None,
            recordBatches: None,
            custom_metadata: None,
        }
    }
}
pub struct FooterBuilder<'a: 'b, 'b> {
    fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a>,
    start_: flatbuffers::WIPOffset<flatbuffers::TableUnfinishedWIPOffset>,
}
impl<'a: 'b, 'b> FooterBuilder<'a, 'b> {
    #[inline]
    pub fn add_version(&mut self, version: MetadataVersion) {
        self.fbb_.push_slot::<MetadataVersion>(
            Footer::VT_VERSION,
            version,
            MetadataVersion::V1,
        );
    }
    #[inline]
    pub fn add_schema(&mut self, schema: flatbuffers::WIPOffset<Schema<'b>>) {
        self.fbb_
            .push_slot_always::<flatbuffers::WIPOffset<Schema>>(
                Footer::VT_SCHEMA,
                schema,
            );
    }
    #[inline]
    pub fn add_dictionaries(
        &mut self,
        dictionaries: flatbuffers::WIPOffset<flatbuffers::Vector<'b, Block>>,
    ) {
        self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>(
            Footer::VT_DICTIONARIES,
            dictionaries,
        );
    }
    #[inline]
    pub fn add_recordBatches(
        &mut self,
        recordBatches: flatbuffers::WIPOffset<flatbuffers::Vector<'b, Block>>,
    ) {
        self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>(
            Footer::VT_RECORDBATCHES,
            recordBatches,
        );
    }
    #[inline]
    pub fn add_custom_metadata(
        &mut self,
        custom_metadata: flatbuffers::WIPOffset<
            flatbuffers::Vector<'b, flatbuffers::ForwardsUOffset<KeyValue<'b>>>,
        >,
    ) {
        self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>(
            Footer::VT_CUSTOM_METADATA,
            custom_metadata,
        );
    }
    #[inline]
    pub fn new(
        _fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>,
    ) -> FooterBuilder<'a, 'b> {
        let start = _fbb.start_table();
        FooterBuilder {
            fbb_: _fbb,
            start_: start,
        }
    }
    #[inline]
    pub fn finish(self) -> flatbuffers::WIPOffset<Footer<'a>> {
        let o = self.fbb_.end_table(self.start_);
        flatbuffers::WIPOffset::new(o.value())
    }
}

impl std::fmt::Debug for Footer<'_> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let mut ds = f.debug_struct("Footer");
        ds.field("version", &self.version());
        ds.field("schema", &self.schema());
        ds.field("dictionaries", &self.dictionaries());
        ds.field("recordBatches", &self.recordBatches());
        ds.field("custom_metadata", &self.custom_metadata());
        ds.finish()
    }
}
#[inline]
#[deprecated(since = "2.0.0", note = "Deprecated in favor of `root_as...` methods.")]
pub fn get_root_as_footer<'a>(buf: &'a [u8]) -> Footer<'a> {
    unsafe { flatbuffers::root_unchecked::<Footer<'a>>(buf) }
}

#[inline]
#[deprecated(since = "2.0.0", note = "Deprecated in favor of `root_as...` methods.")]
pub fn get_size_prefixed_root_as_footer<'a>(buf: &'a [u8]) -> Footer<'a> {
    unsafe { flatbuffers::size_prefixed_root_unchecked::<Footer<'a>>(buf) }
}

#[inline]
/// Verifies that a buffer of bytes contains a `Footer`
/// and returns it.
/// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `root_as_footer_unchecked`.
pub fn root_as_footer(buf: &[u8]) -> Result<Footer, flatbuffers::InvalidFlatbuffer> {
    flatbuffers::root::<Footer>(buf)
}
#[inline]
/// Verifies that a buffer of bytes contains a size prefixed
/// `Footer` and returns it.
/// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `size_prefixed_root_as_footer_unchecked`.
pub fn size_prefixed_root_as_footer(
    buf: &[u8],
) -> Result<Footer, flatbuffers::InvalidFlatbuffer> {
    flatbuffers::size_prefixed_root::<Footer>(buf)
}
#[inline]
/// Verifies, with the given options, that a buffer of bytes
/// contains a `Footer` and returns it.
/// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `root_as_footer_unchecked`.
pub fn root_as_footer_with_opts<'b, 'o>(
    opts: &'o flatbuffers::VerifierOptions,
    buf: &'b [u8],
) -> Result<Footer<'b>, flatbuffers::InvalidFlatbuffer> {
    flatbuffers::root_with_opts::<Footer<'b>>(opts, buf)
}
#[inline]
/// Verifies, with the given verifier options, that a buffer of
/// bytes contains a size prefixed `Footer` and returns
/// it. Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `root_as_footer_unchecked`.
pub fn size_prefixed_root_as_footer_with_opts<'b, 'o>(
    opts: &'o flatbuffers::VerifierOptions,
    buf: &'b [u8],
) -> Result<Footer<'b>, flatbuffers::InvalidFlatbuffer> {
    flatbuffers::size_prefixed_root_with_opts::<Footer<'b>>(opts, buf)
}
#[inline]
/// Assumes, without verification, that a buffer of bytes contains a Footer and returns it.
/// # Safety
/// Callers must trust the given bytes do indeed contain a valid `Footer`.
pub unsafe fn root_as_footer_unchecked(buf: &[u8]) -> Footer {
    flatbuffers::root_unchecked::<Footer>(buf)
}
#[inline]
/// Assumes, without verification, that a buffer of bytes contains a size prefixed Footer and returns it.
/// # Safety
/// Callers must trust the given bytes do indeed contain a valid size prefixed `Footer`.
pub unsafe fn size_prefixed_root_as_footer_unchecked(buf: &[u8]) -> Footer {
    flatbuffers::size_prefixed_root_unchecked::<Footer>(buf)
}
#[inline]
pub fn finish_footer_buffer<'a, 'b>(
    fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>,
    root: flatbuffers::WIPOffset<Footer<'a>>,
) {
    fbb.finish(root, None);
}

#[inline]
pub fn finish_size_prefixed_footer_buffer<'a, 'b>(
    fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>,
    root: flatbuffers::WIPOffset<Footer<'a>>,
) {
    fbb.finish_size_prefixed(root, None);
}
