FlatBuffer: how to construct a table with an optional sub-struct/sub-table - flatbuffers

I have a root table and inside the table an optional struct/table. The inner table is optional--it may or may not construct based on other conditions.
Here is an example FlatBuffer schema:
struct A {
value:bool;
}
table B {
...
}
table C {
...
a:A;
b:B;
...
}
Whether to construct A/B is based on other conditions.
Since you aren't allowed to use FlatBufferBuilder nested, do I have to construct them first even they are not needed, and then add_a/add_b very late, after create Cbuilder based on other conditions?
In C++, I didn't figure out a proper way to do that. Any help is appreciated!

Just because you construct objects in pre-order (not nested) doesn't make optional construction any different:
flatbuffers::Offset<B> bo; // default 0, so unused.
if (my_conditions) {
bo = CreateB(fbb, ..);
}
Cbuilder cb;
if (my_conditions) {
cb.add_a(A(..)); // Structs must be created inline.
}
cb.add_b(bo); // This will not be stored if 0.
...

Related

Swift 5.7 RegexBuilder: Nested TryCapture - transform / Mapping Output?

Here in this example I tried to capture two Int values and then capture them together as a struct. This gives a "Thread 1: signal SIGABRT" error.
(NOTE: I know that my example could be fixed by simply not nesting the Captures and handling the pattern matching differently. This is just simplified example code for the sake of this question.)
let intCapture = Regex {
TryCapture(as: Reference(Int.self)) {
OneOrMore(.digit)
} transform: { result in
return Int(result)
}
}
let mainPattern = Regex {
TryCapture(as: Reference(Floor.self)) {
"floor #: "
intCapture
" has "
intCapture
" rooms"
}transform: { ( stringMatch, floorInt, roomInt ) in
return Floor(floorNumber: floorInt, roomCount: roomInt)
}
}
struct Floor {
let floorNumber: Int
let roomCount: Int
}
let testString = "floor #: 34 has 25 rooms"
let floorData = testString.firstMatch(of: mainPattern)
After looking into it, I found that in the mainPattern's 'transform' the 'floorInt' and 'roomInt' are what is causing the problem.
The funny part is that when you look at the 'Quick Help'/Option+click, it shows that they are both type Int! It knows what is there but you are not able to capture it!
Further, when I erase one of them, let's say 'floorInt', it gives this error:
Contextual closure type '(Substring) throws -> Floor?' expects 1 argument, but 2 were used in closure body
So really, even though for SOME reason it does know that there are two captured Int values there, it doesn't let you access them for the sake of the transform.
Not deterred, I was helped out in another question by a very helpful user who pointed me to the Evolution submission where they mentioned a .mapOutput, but sadly it seems this particular feature was never implemented!
Is there no real way to create a new transformed value from nested transformed values like this? Any help would be greatly appreciated.

Run a regex on a Supply or other stream-like sequence?

Suppose I have a Supply, Channel, IO::Handle, or similar stream-like source of text, and I want to scan it for substrings matching a regex. I can't be sure that matching substrings do not cross chunk boundaries. The total length is potentially infinite and cannot be slurped into memory.
One way this would be possible is if I could instantiate a regex matching engine and feed it chunks of text while it maintains its state. But I don't see any way to do that -- I only see methods to run the match engine to completion.
Is this possible?
After some more searching, I may have answered my own question. Specifically, it seems Seq.comb is capable of combining chunks and lazily processing them:
my $c = supply {
whenever Supply.interval(1.0) -> $v {
my $letter = do if ($v mod 2 == 0) { "a" } else { "b" };
my $chunk = $letter x ($v + 1);
say "Pushing {$chunk}";
emit($chunk);
}
};
my $c2 = $c.comb(/a+b+/);
react {
whenever $c2 -> $v {
say "Got {$v}";
}
}
See also the concurrency features used to construct this example.

How do I use a variable as the data type for a different variable?

If I have the data type of something stored in the variable data_type, how can I create a new variable with the data type defined in this variable?
For example:
struct a {
var: String,
}
struct b {
var: String,
}
let var_type = "a";
let variable: var_type { var: "abc" }; // creates struct var_type
As long as you know all of your types at compile time, it is possible to transform unstructured data into typed data based on some value in the data. This is exactly what is done by the popular serde crate
Without knowing the use case, it's difficult to address the question precisely, yet the code below gives two examples about how to accomplish type-mapping using an enum (though match could be used to map any data to any type that is known at compile time).
enum VarType {
A(String),
B(String),
Unknown(String),
}
fn main() {
let _var1 = VarType::A("abc".to_string());
let _var2 = VarType::B("xyz".to_string());
let data = vec![("a", "abc"), ("b", "xyz")];
for item in data {
let (data_type, value) = item;
match data_type {
"a" => VarType::A(value.to_string()),
"b" => VarType::B(value.to_string()),
_ => VarType::Unknown(value.to_string()),
};
}
}
As Isak van Bakel, most said rust is static. However, if you have a list of all the possible structures, you can. (assuming your using serde here!). There is currently
a interesting question discussing polymorphic de-serialisation here, i suggest you take a look as it may help!
You can't. Rust is statically typed.

Flatbuffers: How to allow multiple types for a single field

I'm writing a communication protocol schema for a list of parameters which can be of multiple values: uint64, float64, string or bool.
How can I set a table field to a union of multiple primitive scalar & non-scalar primitive type?
I've already tried using a union of those types, but I end up with the following error when building:
$ schemas/foobar.fbs:28: 0: error: type referenced but not defined
(check namespace): uint64, originally at: schemas/request.fbs:5
Here's the schema in its current state:
namespace Foobar;
enum RequestCode : uint16 { Noop, Get, Set, BulkGet, BulkSet }
union ParameterValue { uint64, float64, bool, string }
table Parameter {
name:string;
value:ParameterValue;
unit:string;
}
table Request {
code:RequestCode = Noop;
payload:[Parameter];
}
table Result {
request:Request;
success:bool = true;
payload:[Parameter];
}
The end result I'm looking for is the Request and Result tables to contain a list of parameters, where a parameter contains a name and value, and optionally the units.
Thx in advance!
Post-answer solution:
Here's what I came up with in the end, thx to Aardappel.
namespace foobar;
enum RequestCode : uint16 { Noop, Get, Set, BulkGet, BulkSet }
union ValueType { UnsignedInteger, SignedInteger, RealNumber, Boolean, Text }
table UnsignedInteger {
value:uint64 = 0;
}
table SignedInteger {
value:int64 = 0;
}
table RealNumber {
value:float64 = 0.0;
}
table Boolean {
value:bool = false;
}
table Text {
value:string (required);
}
table Parameter {
name:string (required);
valueType:ValueType;
unit:string;
}
table Request {
code:RequestCode = Noop;
payload:[Parameter];
}
table Result {
request:Request (required);
success:bool = true;
payload:[Parameter];
}
You currently can't put scalars directly in a union, so you'd have to wrap these in a table or a struct, where struct would likely be the most efficient, e.g.
struct UInt64 { u:uint64 }
union ParameterValue { UInt64, Float64, Bool, string }
This is because a union must be uniformly the same size, so it only allows types to which you can have an offset.
Generally though, FlatBuffers is a strongly typed system, and the schema you are creating here is undoing that by emulating dynamically typed data, since your data is essentially a list of (string, any type) pairs. You may be better off with a system designed for this particular use case, such as FlexBuffers (https://google.github.io/flatbuffers/flexbuffers.html, currently only C++) which explicitly has a map type that is all string -> any type pairs.
Of course, even better is to not store data so generically, but instead make a new schema for each type of request and response you have, and make parameter names into fields, rather than serialized data. This is by far the most efficient, and type safe.

Alternative to nested if for conditional logic

Is there a design pattern or methodology or language that allows you to write complex conditional logic beyond just nested Ifs?
At the very least, does this kind of question or problem have a name? I was unable to find anything here or through Google that described what I was trying to solve that wasn't just, replace your IF with a Switch statement.
I'm playing around with a script to generate a bunch of data. As part of this, I'd like to add in a lot of branching conditional logic that should provide variety as well as block off certain combinations.
Something like, If User is part of group A, then they can't be part of group B, and if they have Attribute C, then that limits them to characteristic 5 or 6, but nothing below or above that.
The answer is simple: refactoring.
Let's take an example (pseudo-code):
if (a) {
if (b) {
if (c) {
// do something
}
}
}
can be replaced by:
if (a && b && c) {
// do something
}
Now, say that a, b and c are complex predicates which makes the code hard to read, for example:
if (visitorIsInActiveTestCell(visitor) &&
!specialOptOutConditionsApply(request, visitor) &&
whatEverWeWantToCheckHere(bla, blabla)) {
// do something
}
we can refactor it as well and create a new method:
def shouldDoSomething(request, visitor, bla, blabla) {
return visitorIsInActiveTestCell(visitor) &&
!specialOptOutConditionsApply(request, visitor) &&
whatEverWeWantToCheckHere(bla, blabla)
}
and now our if condition isn't nested and becomes easier to read and understand:
if (shouldDoSomething(request, visitor, bla, blabla)) {
// do something
}
Sometimes it's not straightforward to extract such logic and refactor, and it may require taking some time to think about it, but I haven't yet ran into an example in which it was impossible.
All of the foregoing answers seem to miss the question.
One of the patterns that frequently occurs in hardware-interface looks like this:
if (something) {
step1;
if ( the result of step1) {
step2;
if (the result of step2) {
step3;
... and so on
}}}...
This structure cannot be collapsed into a logical conjunction, as each step is dependent on the result of the previous one, and may itself have internal conditions.
In assembly code, it would be a simple matter of test and branch to a common target; i.e., the dreaded "go to". In C, you end up with a pile of indented code that after about 8 levels is very difficult to read.
About the best that I've been able to come up with is:
while( true) {
if ( !something)
break;
step1
if ( ! result of step1)
break;
step2
if ( ! result of step2)
break;
step3
...
break;
}
Does anyone have a better solution?
It is possible you want to replace your conditional logic with polymorphism, assuming you are using an object-oriented language.
That is, instead of:
class Bird:
#...
def getSpeed(self):
if self.type == EUROPEAN:
return self.getBaseSpeed();
elif self.type == AFRICAN:
return self.getBaseSpeed() - self.getLoadFactor() * self.numberOfCoconuts;
elif self.type == NORWEGIAN_BLUE:
return 0 if isNailed else self.getBaseSpeed(self.voltage)
else:
raise Exception("Should be unreachable")
You can say:
class Bird:
#...
def getSpeed(self):
pass
class European(Bird):
def getSpeed(self):
return self.getBaseSpeed()
class African(Bird):
def getSpeed(self):
return self.getBaseSpeed() - self.getLoadFactor() * self.numberOfCoconuts
class NorwegianBlue(Bird):
def getSpeed():
return 0 if self.isNailed else self.getBaseSpeed(self.voltage)
# Somewhere in client code
speed = bird.getSpeed()
Taken from here.