I have the following FlatBuffers schema (simplified):
table StringNode {
prefix: StringNode;
suffix: StringNode;
value: string (required);
}
table NodesData {
url1: StringNode (required);
url2: StringNode (required);
url3: StringNode (required);
}
root_type NodesData;
Is there a way to iterate all StringNode
s without having separate urls: [StringNode]
and adding them while encoding?
I don't see anything similar in generated Rust code.
PS. The Rust code can be generated using flatc --rust filename
. here is what i have:
// automatically generated by the FlatBuffers compiler, do not modify
use std::mem;
use std::cmp::Ordering;
extern crate flatbuffers;
use self::flatbuffers::{EndianScalar, Follow};
#[allow(unused_imports, dead_code)]
pub mod com {
use std::mem;
use std::cmp::Ordering;
extern crate flatbuffers;
use self::flatbuffers::{EndianScalar, Follow};
#[allow(unused_imports, dead_code)]
pub mod company {
use std::mem;
use std::cmp::Ordering;
extern crate flatbuffers;
use self::flatbuffers::{EndianScalar, Follow};
#[allow(unused_imports, dead_code)]
pub mod project {
use std::mem;
use std::cmp::Ordering;
extern crate flatbuffers;
use self::flatbuffers::{EndianScalar, Follow};
#[allow(unused_imports, dead_code)]
pub mod fb {
use std::mem;
use std::cmp::Ordering;
extern crate flatbuffers;
use self::flatbuffers::{EndianScalar, Follow};
#[allow(unused_imports, dead_code)]
pub mod node {
use std::mem;
use std::cmp::Ordering;
extern crate flatbuffers;
use self::flatbuffers::{EndianScalar, Follow};
pub enum StringNodeOffset {}
#[derive(Copy, Clone, PartialEq)]
pub struct StringNode<'a> {
pub _tab: flatbuffers::Table<'a>,
}
impl<'a> flatbuffers::Follow<'a> for StringNode<'a> {
type Inner = StringNode<'a>;
#[inline]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Self { _tab: flatbuffers::Table { buf, loc } }
}
}
impl<'a> StringNode<'a> {
#[inline]
pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
StringNode { _tab: table }
}
#[allow(unused_mut)]
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(
_fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>,
args: &'args StringNodeArgs<'args>) -> flatbuffers::WIPOffset<StringNode<'bldr>> {
let mut builder = StringNodeBuilder::new(_fbb);
if let Some(x) = args.value { builder.add_value(x); }
if let Some(x) = args.suffix { builder.add_suffix(x); }
if let Some(x) = args.prefix { builder.add_prefix(x); }
builder.finish()
}
pub const VT_PREFIX: flatbuffers::VOffsetT = 4;
pub const VT_SUFFIX: flatbuffers::VOffsetT = 6;
pub const VT_VALUE: flatbuffers::VOffsetT = 8;
#[inline]
pub fn prefix(&self) -> Option<StringNode<'a>> {
self._tab.get::<flatbuffers::ForwardsUOffset<StringNode>>(StringNode::VT_PREFIX, None)
}
#[inline]
pub fn suffix(&self) -> Option<StringNode<'a>> {
self._tab.get::<flatbuffers::ForwardsUOffset<StringNode>>(StringNode::VT_SUFFIX, None)
}
#[inline]
pub fn value(&self) -> &'a str {
self._tab.get::<flatbuffers::ForwardsUOffset<&str>>(StringNode::VT_VALUE, None).unwrap()
}
}
impl flatbuffers::Verifiable for StringNode<'_> {
#[inline]
fn run_verifier(
v: &mut flatbuffers::Verifier, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.visit_table(pos)?
.visit_field::<flatbuffers::ForwardsUOffset<StringNode>>(&"prefix", Self::VT_PREFIX, false)?
.visit_field::<flatbuffers::ForwardsUOffset<StringNode>>(&"suffix", Self::VT_SUFFIX, false)?
.visit_field::<flatbuffers::ForwardsUOffset<&str>>(&"value", Self::VT_VALUE, true)?
.finish();
Ok(())
}
}
pub struct StringNodeArgs<'a> {
pub prefix: Option<flatbuffers::WIPOffset<StringNode<'a>>>,
pub suffix: Option<flatbuffers::WIPOffset<StringNode<'a>>>,
pub value: Option<flatbuffers::WIPOffset<&'a str>>,
}
impl<'a> Default for StringNodeArgs<'a> {
#[inline]
fn default() -> Self {
StringNodeArgs {
prefix: None,
suffix: None,
value: None, // required field
}
}
}
pub struct StringNodeBuilder<'a: 'b, 'b> {
fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a>,
start_: flatbuffers::WIPOffset<flatbuffers::TableUnfinishedWIPOffset>,
}
impl<'a: 'b, 'b> StringNodeBuilder<'a, 'b> {
#[inline]
pub fn add_prefix(&mut self, prefix: flatbuffers::WIPOffset<StringNode<'b >>) {
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<StringNode>>(StringNode::VT_PREFIX, prefix);
}
#[inline]
pub fn add_suffix(&mut self, suffix: flatbuffers::WIPOffset<StringNode<'b >>) {
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<StringNode>>(StringNode::VT_SUFFIX, suffix);
}
#[inline]
pub fn add_value(&mut self, value: flatbuffers::WIPOffset<&'b str>) {
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>(StringNode::VT_VALUE, value);
}
#[inline]
pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>) -> StringNodeBuilder<'a, 'b> {
let start = _fbb.start_table();
StringNodeBuilder {
fbb_: _fbb,
start_: start,
}
}
#[inline]
pub fn finish(self) -> flatbuffers::WIPOffset<StringNode<'a>> {
let o = self.fbb_.end_table(self.start_);
self.fbb_.required(o, StringNode::VT_VALUE,"value");
flatbuffers::WIPOffset::new(o.value())
}
}
impl std::fmt::Debug for StringNode<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut ds = f.debug_struct("StringNode");
ds.field("prefix", &self.prefix());
ds.field("suffix", &self.suffix());
ds.field("value", &self.value());
ds.finish()
}
}
pub enum NodesDataOffset {}
#[derive(Copy, Clone, PartialEq)]
pub struct NodesData<'a> {
pub _tab: flatbuffers::Table<'a>,
}
impl<'a> flatbuffers::Follow<'a> for NodesData<'a> {
type Inner = NodesData<'a>;
#[inline]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Self { _tab: flatbuffers::Table { buf, loc } }
}
}
impl<'a> NodesData<'a> {
#[inline]
pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
NodesData { _tab: table }
}
#[allow(unused_mut)]
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(
_fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>,
args: &'args NodesDataArgs<'args>) -> flatbuffers::WIPOffset<NodesData<'bldr>> {
let mut builder = NodesDataBuilder::new(_fbb);
if let Some(x) = args.url3 { builder.add_url3(x); }
if let Some(x) = args.url2 { builder.add_url2(x); }
if let Some(x) = args.url1 { builder.add_url1(x); }
builder.finish()
}
pub const VT_URL1: flatbuffers::VOffsetT = 4;
pub const VT_URL2: flatbuffers::VOffsetT = 6;
pub const VT_URL3: flatbuffers::VOffsetT = 8;
#[inline]
pub fn url1(&self) -> StringNode<'a> {
self._tab.get::<flatbuffers::ForwardsUOffset<StringNode>>(NodesData::VT_URL1, None).unwrap()
}
#[inline]
pub fn url2(&self) -> StringNode<'a> {
self._tab.get::<flatbuffers::ForwardsUOffset<StringNode>>(NodesData::VT_URL2, None).unwrap()
}
#[inline]
pub fn url3(&self) -> StringNode<'a> {
self._tab.get::<flatbuffers::ForwardsUOffset<StringNode>>(NodesData::VT_URL3, None).unwrap()
}
}
impl flatbuffers::Verifiable for NodesData<'_> {
#[inline]
fn run_verifier(
v: &mut flatbuffers::Verifier, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.visit_table(pos)?
.visit_field::<flatbuffers::ForwardsUOffset<StringNode>>(&"url1", Self::VT_URL1, true)?
.visit_field::<flatbuffers::ForwardsUOffset<StringNode>>(&"url2", Self::VT_URL2, true)?
.visit_field::<flatbuffers::ForwardsUOffset<StringNode>>(&"url3", Self::VT_URL3, true)?
.finish();
Ok(())
}
}
pub struct NodesDataArgs<'a> {
pub url1: Option<flatbuffers::WIPOffset<StringNode<'a>>>,
pub url2: Option<flatbuffers::WIPOffset<StringNode<'a>>>,
pub url3: Option<flatbuffers::WIPOffset<StringNode<'a>>>,
}
impl<'a> Default for NodesDataArgs<'a> {
#[inline]
fn default() -> Self {
NodesDataArgs {
url1: None, // required field
url2: None, // required field
url3: None, // required field
}
}
}
pub struct NodesDataBuilder<'a: 'b, 'b> {
fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a>,
start_: flatbuffers::WIPOffset<flatbuffers::TableUnfinishedWIPOffset>,
}
impl<'a: 'b, 'b> NodesDataBuilder<'a, 'b> {
#[inline]
pub fn add_url1(&mut self, url1: flatbuffers::WIPOffset<StringNode<'b >>) {
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<StringNode>>(NodesData::VT_URL1, url1);
}
#[inline]
pub fn add_url2(&mut self, url2: flatbuffers::WIPOffset<StringNode<'b >>) {
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<StringNode>>(NodesData::VT_URL2, url2);
}
#[inline]
pub fn add_url3(&mut self, url3: flatbuffers::WIPOffset<StringNode<'b >>) {
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<StringNode>>(NodesData::VT_URL3, url3);
}
#[inline]
pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>) -> NodesDataBuilder<'a, 'b> {
let start = _fbb.start_table();
NodesDataBuilder {
fbb_: _fbb,
start_: start,
}
}
#[inline]
pub fn finish(self) -> flatbuffers::WIPOffset<NodesData<'a>> {
let o = self.fbb_.end_table(self.start_);
self.fbb_.required(o, NodesData::VT_URL1,"url1");
self.fbb_.required(o, NodesData::VT_URL2,"url2");
self.fbb_.required(o, NodesData::VT_URL3,"url3");
flatbuffers::WIPOffset::new(o.value())
}
}
impl std::fmt::Debug for NodesData<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut ds = f.debug_struct("NodesData");
ds.field("url1", &self.url1());
ds.field("url2", &self.url2());
ds.field("url3", &self.url3());
ds.finish()
}
}
#[inline]
#[deprecated(since="2.0.0", note="Deprecated in favor of `root_as...` methods.")]
pub fn get_root_as_nodes_data<'a>(buf: &'a [u8]) -> NodesData<'a> {
unsafe { flatbuffers::root_unchecked::<NodesData<'a>>(buf) }
}
#[inline]
#[deprecated(since="2.0.0", note="Deprecated in favor of `root_as...` methods.")]
pub fn get_size_prefixed_root_as_nodes_data<'a>(buf: &'a [u8]) -> NodesData<'a> {
unsafe { flatbuffers::size_prefixed_root_unchecked::<NodesData<'a>>(buf) }
}
#[inline]
/// Verifies that a buffer of bytes contains a `NodesData`
/// 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_nodes_data_unchecked`.
pub fn root_as_nodes_data(buf: &[u8]) -> Result<NodesData, flatbuffers::InvalidFlatbuffer> {
flatbuffers::root::<NodesData>(buf)
}
#[inline]
/// Verifies that a buffer of bytes contains a size prefixed
/// `NodesData` 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_nodes_data_unchecked`.
pub fn size_prefixed_root_as_nodes_data(buf: &[u8]) -> Result<NodesData, flatbuffers::InvalidFlatbuffer> {
flatbuffers::size_prefixed_root::<NodesData>(buf)
}
#[inline]
/// Verifies, with the given options, that a buffer of bytes
/// contains a `NodesData` 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_nodes_data_unchecked`.
pub fn root_as_nodes_data_with_opts<'b, 'o>(
opts: &'o flatbuffers::VerifierOptions,
buf: &'b [u8],
) -> Result<NodesData<'b>, flatbuffers::InvalidFlatbuffer> {
flatbuffers::root_with_opts::<NodesData<'b>>(opts, buf)
}
#[inline]
/// Verifies, with the given verifier options, that a buffer of
/// bytes contains a size prefixed `NodesData` 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_nodes_data_unchecked`.
pub fn size_prefixed_root_as_nodes_data_with_opts<'b, 'o>(
opts: &'o flatbuffers::VerifierOptions,
buf: &'b [u8],
) -> Result<NodesData<'b>, flatbuffers::InvalidFlatbuffer> {
flatbuffers::size_prefixed_root_with_opts::<NodesData<'b>>(opts, buf)
}
#[inline]
/// Assumes, without verification, that a buffer of bytes contains a NodesData and returns it.
/// # Safety
/// Callers must trust the given bytes do indeed contain a valid `NodesData`.
pub unsafe fn root_as_nodes_data_unchecked(buf: &[u8]) -> NodesData {
flatbuffers::root_unchecked::<NodesData>(buf)
}
#[inline]
/// Assumes, without verification, that a buffer of bytes contains a size prefixed NodesData and returns it.
/// # Safety
/// Callers must trust the given bytes do indeed contain a valid size prefixed `NodesData`.
pub unsafe fn size_prefixed_root_as_nodes_data_unchecked(buf: &[u8]) -> NodesData {
flatbuffers::size_prefixed_root_unchecked::<NodesData>(buf)
}
#[inline]
pub fn finish_nodes_data_buffer<'a, 'b>(
fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>,
root: flatbuffers::WIPOffset<NodesData<'a>>) {
fbb.finish(root, None);
}
#[inline]
pub fn finish_size_prefixed_nodes_data_buffer<'a, 'b>(fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>, root: flatbuffers::WIPOffset<NodesData<'a>>) {
fbb.finish_size_prefixed(root, None);
}
} // pub mod node
} // pub mod fb
} // pub mod project
} // pub mod company
} // pub mod com
But the questions is "even if the getter code is not generated by flatc Rust plugin, is it doable in general?". If following db concept that should be doable.
PPS. flatc "2.0.0" is used, flatbuffers "2.0.0" crate is used.
No, you can't. FlatBuffer fields are not necessarily contiguous in memory, and they potentially all have different types, so there is no way to iterate them.
While that potentially could be implemented with sufficient trickery (visitors?) there isn't a lot of point, especially in a system that is efficiency oriented.
Like you already say so yourself, you really want to be using a [StringNode]
in cases like this.