mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-16 01:07:29 +00:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a54ca1e759 | ||
|
|
5b3fadcc16 | ||
|
|
872a497464 | ||
|
|
e301702964 | ||
|
|
f7b734438d | ||
|
|
5792623df4 | ||
|
|
0edb275285 | ||
|
|
acc6a20d39 | ||
|
|
04cd037ba2 | ||
|
|
e1c5db988a | ||
|
|
b80142b901 | ||
|
|
54418f371b | ||
|
|
c92e78a9f8 | ||
|
|
d243b904cc | ||
|
|
374f8fb5fb | ||
|
|
dadbff5714 |
10
.github/labeler.yml
vendored
10
.github/labeler.yml
vendored
@@ -18,6 +18,12 @@ swift:
|
|||||||
- tests/swift/**
|
- tests/swift/**
|
||||||
- src/idl_gen_swift.cpp
|
- src/idl_gen_swift.cpp
|
||||||
|
|
||||||
|
nim:
|
||||||
|
- '**/*.nim'
|
||||||
|
- nim/**/*
|
||||||
|
- src/idl_gen_nim.cpp
|
||||||
|
- src/bfbs_gen_nim.cpp
|
||||||
|
|
||||||
javascript:
|
javascript:
|
||||||
- '**/*.js'
|
- '**/*.js'
|
||||||
- src/idl_gen_ts.cpp
|
- src/idl_gen_ts.cpp
|
||||||
@@ -61,7 +67,7 @@ rust:
|
|||||||
- '**/*.rs'
|
- '**/*.rs'
|
||||||
- rust/**/*
|
- rust/**/*
|
||||||
- src/idl_gen_rust.cpp
|
- src/idl_gen_rust.cpp
|
||||||
|
|
||||||
dart:
|
dart:
|
||||||
- '**/*.dart'
|
- '**/*.dart'
|
||||||
- src/idl_gen_dart.cpp
|
- src/idl_gen_dart.cpp
|
||||||
@@ -88,4 +94,4 @@ CI:
|
|||||||
|
|
||||||
grpc:
|
grpc:
|
||||||
- grpc/**/*
|
- grpc/**/*
|
||||||
- src/idl_gen_grpc.cpp
|
- src/idl_gen_grpc.cpp
|
||||||
|
|||||||
16
.github/workflows/build.yml
vendored
16
.github/workflows/build.yml
vendored
@@ -477,6 +477,22 @@ jobs:
|
|||||||
working-directory: tests
|
working-directory: tests
|
||||||
run: bash DartTest.sh
|
run: bash DartTest.sh
|
||||||
|
|
||||||
|
build-nim:
|
||||||
|
name: Build Nim
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: flatc
|
||||||
|
# FIXME: make test script not rely on flatc
|
||||||
|
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . && make -j
|
||||||
|
- uses: jiro4989/setup-nim-action@v1
|
||||||
|
- name: install library
|
||||||
|
working-directory: nim
|
||||||
|
run: nimble -y develop
|
||||||
|
- name: test
|
||||||
|
working-directory: tests/nim
|
||||||
|
run: python3 testnim.py
|
||||||
|
|
||||||
release-digests:
|
release-digests:
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
needs: [build-linux, build-windows, build-mac-intel, build-mac-universal]
|
needs: [build-linux, build-windows, build-mac-intel, build-mac-universal]
|
||||||
|
|||||||
12
CHANGELOG.md
12
CHANGELOG.md
@@ -4,6 +4,14 @@ All major or breaking changes will be documented in this file, as well as any
|
|||||||
new features that should be highlighted. Minor fixes or improvements are not
|
new features that should be highlighted. Minor fixes or improvements are not
|
||||||
necessarily listed.
|
necessarily listed.
|
||||||
|
|
||||||
|
## 22.10.25 (Oct 25 2002)
|
||||||
|
|
||||||
|
* Added Nim language support with generator and runtime libraries (#7534).
|
||||||
|
|
||||||
|
## 22.9.29 (Sept 29 2022)
|
||||||
|
|
||||||
|
* Rust soundness fixes to avoid the crate from bing labelled unsafe (#7518).
|
||||||
|
|
||||||
## 22.9.24 (Sept 24 2022)
|
## 22.9.24 (Sept 24 2022)
|
||||||
|
|
||||||
* 20 Major releases in a row? Nope, we switched to a new
|
* 20 Major releases in a row? Nope, we switched to a new
|
||||||
@@ -23,8 +31,8 @@ necessarily listed.
|
|||||||
`AlignOf()` for structs (#7520).
|
`AlignOf()` for structs (#7520).
|
||||||
|
|
||||||
* C# has an
|
* C# has an
|
||||||
[offical Nuget package](https://www.nuget.org/packages/Google.FlatBuffers) now
|
[official Nuget package](https://www.nuget.org/packages/Google.FlatBuffers)
|
||||||
(#7496).
|
now (#7496).
|
||||||
|
|
||||||
## 2.0.8 (Aug 29 2022)
|
## 2.0.8 (Aug 29 2022)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
set(VERSION_MAJOR 22)
|
set(VERSION_MAJOR 22)
|
||||||
set(VERSION_MINOR 9)
|
set(VERSION_MINOR 10)
|
||||||
set(VERSION_PATCH 24)
|
set(VERSION_PATCH 25)
|
||||||
set(VERSION_COMMIT 0)
|
set(VERSION_COMMIT 0)
|
||||||
|
|
||||||
find_program(GIT git)
|
find_program(GIT git)
|
||||||
|
|||||||
@@ -182,6 +182,7 @@ set(FlatBuffers_Compiler_SRCS
|
|||||||
src/flatc_main.cpp
|
src/flatc_main.cpp
|
||||||
src/bfbs_gen.h
|
src/bfbs_gen.h
|
||||||
src/bfbs_gen_lua.h
|
src/bfbs_gen_lua.h
|
||||||
|
src/bfbs_gen_nim.h
|
||||||
src/bfbs_namer.h
|
src/bfbs_namer.h
|
||||||
include/flatbuffers/code_generators.h
|
include/flatbuffers/code_generators.h
|
||||||
src/binary_annotator.h
|
src/binary_annotator.h
|
||||||
@@ -189,6 +190,7 @@ set(FlatBuffers_Compiler_SRCS
|
|||||||
src/annotated_binary_text_gen.h
|
src/annotated_binary_text_gen.h
|
||||||
src/annotated_binary_text_gen.cpp
|
src/annotated_binary_text_gen.cpp
|
||||||
src/bfbs_gen_lua.cpp
|
src/bfbs_gen_lua.cpp
|
||||||
|
src/bfbs_gen_nim.cpp
|
||||||
src/code_generators.cpp
|
src/code_generators.cpp
|
||||||
grpc/src/compiler/schema_interface.h
|
grpc/src/compiler/schema_interface.h
|
||||||
grpc/src/compiler/cpp_generator.h
|
grpc/src/compiler/cpp_generator.h
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
Pod::Spec.new do |s|
|
Pod::Spec.new do |s|
|
||||||
s.name = 'FlatBuffers'
|
s.name = 'FlatBuffers'
|
||||||
s.version = '22.9.24'
|
s.version = '22.10.25'
|
||||||
s.summary = 'FlatBuffers: Memory Efficient Serialization Library'
|
s.summary = 'FlatBuffers: Memory Efficient Serialization Library'
|
||||||
|
|
||||||
s.description = "FlatBuffers is a cross platform serialization library architected for
|
s.description = "FlatBuffers is a cross platform serialization library architected for
|
||||||
@@ -11,11 +11,11 @@ Pod::Spec.new do |s|
|
|||||||
s.homepage = 'https://github.com/google/flatbuffers'
|
s.homepage = 'https://github.com/google/flatbuffers'
|
||||||
s.license = { :type => 'Apache2.0', :file => 'LICENSE' }
|
s.license = { :type => 'Apache2.0', :file => 'LICENSE' }
|
||||||
s.author = { 'mustii' => 'mustii@mmk.one' }
|
s.author = { 'mustii' => 'mustii@mmk.one' }
|
||||||
s.source = { :git => 'https://github.com/mustiikhalil/flatbuffers.git', :tag => s.version.to_s, :submodules => true }
|
s.source = { :git => 'https://github.com/google/flatbuffers.git', :tag => s.version.to_s, :submodules => true }
|
||||||
|
|
||||||
s.ios.deployment_target = '11.0'
|
s.ios.deployment_target = '11.0'
|
||||||
s.osx.deployment_target = '10.14'
|
s.osx.deployment_target = '10.14'
|
||||||
|
|
||||||
s.swift_version = '5.0'
|
s.swift_version = '5.0'
|
||||||
s.source_files = 'Sources/Flatbuffers/*.swift'
|
s.source_files = 'swift/Sources/Flatbuffers/*.swift'
|
||||||
end
|
end
|
||||||
@@ -32,5 +32,6 @@ let package = Package(
|
|||||||
.target(
|
.target(
|
||||||
name: "FlatBuffers",
|
name: "FlatBuffers",
|
||||||
dependencies: [],
|
dependencies: [],
|
||||||
|
path: "swift/Sources",
|
||||||
exclude: ["Documentation.docc/Resources/code/swift"]),
|
exclude: ["Documentation.docc/Resources/code/swift"]),
|
||||||
])
|
])
|
||||||
@@ -31,6 +31,7 @@ let package = Package(
|
|||||||
targets: [
|
targets: [
|
||||||
.target(
|
.target(
|
||||||
name: "FlatBuffers",
|
name: "FlatBuffers",
|
||||||
dependencies: []),
|
dependencies: [],
|
||||||
|
path: "swift/Sources")
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ class Animal : Table() {
|
|||||||
return if(o != 0) bb.getShort(o + bb_pos).toUShort() else 0u
|
return if(o != 0) bb.getShort(o + bb_pos).toUShort() else 0u
|
||||||
}
|
}
|
||||||
companion object {
|
companion object {
|
||||||
fun validateVersion() = Constants.FLATBUFFERS_22_9_24()
|
fun validateVersion() = Constants.FLATBUFFERS_22_10_25()
|
||||||
fun getRootAsAnimal(_bb: ByteBuffer): Animal = getRootAsAnimal(_bb, Animal())
|
fun getRootAsAnimal(_bb: ByteBuffer): Animal = getRootAsAnimal(_bb, Animal())
|
||||||
fun getRootAsAnimal(_bb: ByteBuffer, obj: Animal): Animal {
|
fun getRootAsAnimal(_bb: ByteBuffer, obj: Animal): Animal {
|
||||||
_bb.order(ByteOrder.LITTLE_ENDIAN)
|
_bb.order(ByteOrder.LITTLE_ENDIAN)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: flat_buffers
|
name: flat_buffers
|
||||||
version: 22.9.24
|
version: 22.10.25
|
||||||
description: FlatBuffers reading and writing library for Dart. Based on original work by Konstantin Scheglov and Paul Berry of the Dart SDK team.
|
description: FlatBuffers reading and writing library for Dart. Based on original work by Konstantin Scheglov and Paul Berry of the Dart SDK team.
|
||||||
homepage: https://github.com/google/flatbuffers
|
homepage: https://github.com/google/flatbuffers
|
||||||
documentation: https://google.github.io/flatbuffers/index.html
|
documentation: https://google.github.io/flatbuffers/index.html
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ include = `include` string\_constant `;`
|
|||||||
|
|
||||||
namespace\_decl = `namespace` ident ( `.` ident )* `;`
|
namespace\_decl = `namespace` ident ( `.` ident )* `;`
|
||||||
|
|
||||||
attribute\_decl = `attribute` ident | `"`ident`"` `;`
|
attribute\_decl = `attribute` ident | `"` ident `"` `;`
|
||||||
|
|
||||||
type\_decl = ( `table` | `struct` ) ident metadata `{` field\_decl+ `}`
|
type\_decl = ( `table` | `struct` ) ident metadata `{` field\_decl+ `}`
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ type = `bool` | `byte` | `ubyte` | `short` | `ushort` | `int` | `uint` |
|
|||||||
`float32` | `float64` |
|
`float32` | `float64` |
|
||||||
`string` | `[` type `]` | ident
|
`string` | `[` type `]` | ident
|
||||||
|
|
||||||
enumval\_decl = ident [ `=` integer\_constant ]
|
enumval\_decl = ident [ `=` integer\_constant ] metadata
|
||||||
|
|
||||||
metadata = [ `(` commasep( ident [ `:` single\_value ] ) `)` ]
|
metadata = [ `(` commasep( ident [ `:` single\_value ] ) `)` ]
|
||||||
|
|
||||||
|
|||||||
@@ -309,11 +309,11 @@ in the corresponding C++ code. Multiple such lines per item are allowed.
|
|||||||
|
|
||||||
### Attributes
|
### Attributes
|
||||||
|
|
||||||
Attributes may be attached to a declaration, behind a field, or after
|
Attributes may be attached to a declaration, behind a field/enum value,
|
||||||
the name of a table/struct/enum/union. These may either have a value or
|
or after the name of a table/struct/enum/union. These may either have
|
||||||
not. Some attributes like `deprecated` are understood by the compiler;
|
a value or not. Some attributes like `deprecated` are understood by
|
||||||
user defined ones need to be declared with the attribute declaration
|
the compiler; user defined ones need to be declared with the attribute
|
||||||
(like `priority` in the example above), and are
|
declaration (like `priority` in the example above), and are
|
||||||
available to query if you parse the schema at runtime.
|
available to query if you parse the schema at runtime.
|
||||||
This is useful if you write your own code generators/editors etc., and
|
This is useful if you write your own code generators/editors etc., and
|
||||||
you wish to add additional information specific to your tool (such as a
|
you wish to add additional information specific to your tool (such as a
|
||||||
@@ -552,7 +552,7 @@ the world. If this is not practical for you, use explicit field ids, which
|
|||||||
should always generate a merge conflict if two people try to allocate the same
|
should always generate a merge conflict if two people try to allocate the same
|
||||||
id.
|
id.
|
||||||
|
|
||||||
### Schema evolution examples
|
### Schema evolution examples (tables)
|
||||||
|
|
||||||
Some examples to clarify what happens as you change a schema:
|
Some examples to clarify what happens as you change a schema:
|
||||||
|
|
||||||
@@ -614,6 +614,41 @@ Occasionally ok. You've renamed fields, which will break all code (and JSON
|
|||||||
files!) that use this schema, but as long as the change is obvious, this is not
|
files!) that use this schema, but as long as the change is obvious, this is not
|
||||||
incompatible with the actual binary buffers, since those only ever address
|
incompatible with the actual binary buffers, since those only ever address
|
||||||
fields by id/offset.
|
fields by id/offset.
|
||||||
|
|
||||||
|
#### Schema evolution examples (unions)
|
||||||
|
|
||||||
|
Suppose we have the following schema:
|
||||||
|
```
|
||||||
|
union Foo { A, B }
|
||||||
|
```
|
||||||
|
We can add another variant at the end.
|
||||||
|
```
|
||||||
|
union Foo { A, B, another_a: A }
|
||||||
|
```
|
||||||
|
and this will be okay. Old code will not recognize `another_a`.
|
||||||
|
However if we add `another_a` anywhere but the end, e.g.
|
||||||
|
```
|
||||||
|
union Foo { A, another_a: A, B }
|
||||||
|
```
|
||||||
|
this is not okay. When new code writes `another_a`, old code will
|
||||||
|
misinterpret it as `B` (and vice versa). However you can explicitly
|
||||||
|
set the union's "discriminant" value like so:
|
||||||
|
```
|
||||||
|
union Foo { A = 1, another_a: A = 3, B = 2 }
|
||||||
|
```
|
||||||
|
This is okay.
|
||||||
|
|
||||||
|
```
|
||||||
|
union Foo { original_a: A = 1, another_a: A = 3, B = 2 }
|
||||||
|
```
|
||||||
|
Renaming fields will break code and any saved human readable representations,
|
||||||
|
such as json files, but the binary buffers will be the same.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
### Testing whether a field is present in a table
|
### Testing whether a field is present in a table
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import FlatBuffers
|
|||||||
|
|
||||||
public struct models_HelloReply: FlatBufferObject, Verifiable {
|
public struct models_HelloReply: FlatBufferObject, Verifiable {
|
||||||
|
|
||||||
static func validateVersion() { FlatBuffersVersion_22_9_24() }
|
static func validateVersion() { FlatBuffersVersion_22_10_25() }
|
||||||
public var __buffer: ByteBuffer! { return _accessor.bb }
|
public var __buffer: ByteBuffer! { return _accessor.bb }
|
||||||
private var _accessor: Table
|
private var _accessor: Table
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ extension models_HelloReply: Encodable {
|
|||||||
|
|
||||||
public struct models_HelloRequest: FlatBufferObject, Verifiable {
|
public struct models_HelloRequest: FlatBufferObject, Verifiable {
|
||||||
|
|
||||||
static func validateVersion() { FlatBuffersVersion_22_9_24() }
|
static func validateVersion() { FlatBuffersVersion_22_10_25() }
|
||||||
public var __buffer: ByteBuffer! { return _accessor.bb }
|
public var __buffer: ByteBuffer! { return _accessor.bb }
|
||||||
private var _accessor: Table
|
private var _accessor: Table
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ template<typename T, uint16_t length> class Array {
|
|||||||
public:
|
public:
|
||||||
typedef uint16_t size_type;
|
typedef uint16_t size_type;
|
||||||
typedef typename IndirectHelper<IndirectHelperType>::return_type return_type;
|
typedef typename IndirectHelper<IndirectHelperType>::return_type return_type;
|
||||||
typedef VectorIterator<T, return_type> const_iterator;
|
typedef VectorConstIterator<T, return_type> const_iterator;
|
||||||
typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
|
typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
|
||||||
|
|
||||||
// If T is a LE-scalar or a struct (!scalar_tag::value).
|
// If T is a LE-scalar or a struct (!scalar_tag::value).
|
||||||
|
|||||||
@@ -139,8 +139,8 @@
|
|||||||
#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
|
#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
|
||||||
|
|
||||||
#define FLATBUFFERS_VERSION_MAJOR 22
|
#define FLATBUFFERS_VERSION_MAJOR 22
|
||||||
#define FLATBUFFERS_VERSION_MINOR 9
|
#define FLATBUFFERS_VERSION_MINOR 10
|
||||||
#define FLATBUFFERS_VERSION_REVISION 24
|
#define FLATBUFFERS_VERSION_REVISION 25
|
||||||
#define FLATBUFFERS_STRING_EXPAND(X) #X
|
#define FLATBUFFERS_STRING_EXPAND(X) #X
|
||||||
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
|
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
|
||||||
namespace flatbuffers {
|
namespace flatbuffers {
|
||||||
|
|||||||
@@ -76,6 +76,9 @@ template<typename T> struct IndirectHelper {
|
|||||||
static return_type Read(const uint8_t *p, uoffset_t i) {
|
static return_type Read(const uint8_t *p, uoffset_t i) {
|
||||||
return EndianScalar((reinterpret_cast<const T *>(p))[i]);
|
return EndianScalar((reinterpret_cast<const T *>(p))[i]);
|
||||||
}
|
}
|
||||||
|
static return_type Read(uint8_t *p, uoffset_t i) {
|
||||||
|
return Read(const_cast<const uint8_t *>(p), i);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
template<typename T> struct IndirectHelper<Offset<T>> {
|
template<typename T> struct IndirectHelper<Offset<T>> {
|
||||||
typedef const T *return_type;
|
typedef const T *return_type;
|
||||||
@@ -85,13 +88,20 @@ template<typename T> struct IndirectHelper<Offset<T>> {
|
|||||||
p += i * sizeof(uoffset_t);
|
p += i * sizeof(uoffset_t);
|
||||||
return reinterpret_cast<return_type>(p + ReadScalar<uoffset_t>(p));
|
return reinterpret_cast<return_type>(p + ReadScalar<uoffset_t>(p));
|
||||||
}
|
}
|
||||||
|
static mutable_return_type Read(uint8_t *p, uoffset_t i) {
|
||||||
|
p += i * sizeof(uoffset_t);
|
||||||
|
return reinterpret_cast<mutable_return_type>(p + ReadScalar<uoffset_t>(p));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
template<typename T> struct IndirectHelper<const T *> {
|
template<typename T> struct IndirectHelper<const T *> {
|
||||||
typedef const T *return_type;
|
typedef const T *return_type;
|
||||||
typedef T *mutable_return_type;
|
typedef T *mutable_return_type;
|
||||||
static const size_t element_stride = sizeof(T);
|
static const size_t element_stride = sizeof(T);
|
||||||
static return_type Read(const uint8_t *p, uoffset_t i) {
|
static return_type Read(const uint8_t *p, uoffset_t i) {
|
||||||
return reinterpret_cast<const T *>(p + i * sizeof(T));
|
return reinterpret_cast<return_type>(p + i * sizeof(T));
|
||||||
|
}
|
||||||
|
static mutable_return_type Read(uint8_t *p, uoffset_t i) {
|
||||||
|
return reinterpret_cast<mutable_return_type>(p + i * sizeof(T));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -382,7 +382,14 @@ struct EnumVal {
|
|||||||
Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder,
|
Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder,
|
||||||
const Parser &parser) const;
|
const Parser &parser) const;
|
||||||
|
|
||||||
bool Deserialize(const Parser &parser, const reflection::EnumVal *val);
|
bool Deserialize(Parser &parser, const reflection::EnumVal *val);
|
||||||
|
|
||||||
|
flatbuffers::Offset<
|
||||||
|
flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
|
||||||
|
SerializeAttributes(FlatBufferBuilder *builder, const Parser &parser) const;
|
||||||
|
|
||||||
|
bool DeserializeAttributes(Parser &parser,
|
||||||
|
const Vector<Offset<reflection::KeyValue>> *attrs);
|
||||||
|
|
||||||
uint64_t GetAsUInt64() const { return static_cast<uint64_t>(value); }
|
uint64_t GetAsUInt64() const { return static_cast<uint64_t>(value); }
|
||||||
int64_t GetAsInt64() const { return value; }
|
int64_t GetAsInt64() const { return value; }
|
||||||
@@ -392,6 +399,7 @@ struct EnumVal {
|
|||||||
std::string name;
|
std::string name;
|
||||||
std::vector<std::string> doc_comment;
|
std::vector<std::string> doc_comment;
|
||||||
Type union_type;
|
Type union_type;
|
||||||
|
SymbolTable<Value> attributes;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend EnumDef;
|
friend EnumDef;
|
||||||
@@ -653,6 +661,7 @@ struct IDLOptions {
|
|||||||
kRust = 1 << 14,
|
kRust = 1 << 14,
|
||||||
kKotlin = 1 << 15,
|
kKotlin = 1 << 15,
|
||||||
kSwift = 1 << 16,
|
kSwift = 1 << 16,
|
||||||
|
kNim = 1 << 17,
|
||||||
kMAX
|
kMAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
// Ensure the included flatbuffers.h is the same version as when this file was
|
// Ensure the included flatbuffers.h is the same version as when this file was
|
||||||
// generated, otherwise it may not be compatible.
|
// generated, otherwise it may not be compatible.
|
||||||
static_assert(FLATBUFFERS_VERSION_MAJOR == 22 &&
|
static_assert(FLATBUFFERS_VERSION_MAJOR == 22 &&
|
||||||
FLATBUFFERS_VERSION_MINOR == 9 &&
|
FLATBUFFERS_VERSION_MINOR == 10 &&
|
||||||
FLATBUFFERS_VERSION_REVISION == 24,
|
FLATBUFFERS_VERSION_REVISION == 25,
|
||||||
"Non-compatible flatbuffers version included");
|
"Non-compatible flatbuffers version included");
|
||||||
|
|
||||||
namespace reflection {
|
namespace reflection {
|
||||||
@@ -334,7 +334,8 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||||||
VT_NAME = 4,
|
VT_NAME = 4,
|
||||||
VT_VALUE = 6,
|
VT_VALUE = 6,
|
||||||
VT_UNION_TYPE = 10,
|
VT_UNION_TYPE = 10,
|
||||||
VT_DOCUMENTATION = 12
|
VT_DOCUMENTATION = 12,
|
||||||
|
VT_ATTRIBUTES = 14
|
||||||
};
|
};
|
||||||
const flatbuffers::String *name() const {
|
const flatbuffers::String *name() const {
|
||||||
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
||||||
@@ -354,6 +355,9 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||||||
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
|
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
|
||||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
|
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
|
||||||
}
|
}
|
||||||
|
const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const {
|
||||||
|
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
|
||||||
|
}
|
||||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||||
return VerifyTableStart(verifier) &&
|
return VerifyTableStart(verifier) &&
|
||||||
VerifyOffsetRequired(verifier, VT_NAME) &&
|
VerifyOffsetRequired(verifier, VT_NAME) &&
|
||||||
@@ -364,6 +368,9 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||||||
VerifyOffset(verifier, VT_DOCUMENTATION) &&
|
VerifyOffset(verifier, VT_DOCUMENTATION) &&
|
||||||
verifier.VerifyVector(documentation()) &&
|
verifier.VerifyVector(documentation()) &&
|
||||||
verifier.VerifyVectorOfStrings(documentation()) &&
|
verifier.VerifyVectorOfStrings(documentation()) &&
|
||||||
|
VerifyOffset(verifier, VT_ATTRIBUTES) &&
|
||||||
|
verifier.VerifyVector(attributes()) &&
|
||||||
|
verifier.VerifyVectorOfTables(attributes()) &&
|
||||||
verifier.EndTable();
|
verifier.EndTable();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -384,6 +391,9 @@ struct EnumValBuilder {
|
|||||||
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
||||||
fbb_.AddOffset(EnumVal::VT_DOCUMENTATION, documentation);
|
fbb_.AddOffset(EnumVal::VT_DOCUMENTATION, documentation);
|
||||||
}
|
}
|
||||||
|
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes) {
|
||||||
|
fbb_.AddOffset(EnumVal::VT_ATTRIBUTES, attributes);
|
||||||
|
}
|
||||||
explicit EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
explicit EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||||
: fbb_(_fbb) {
|
: fbb_(_fbb) {
|
||||||
start_ = fbb_.StartTable();
|
start_ = fbb_.StartTable();
|
||||||
@@ -401,9 +411,11 @@ inline flatbuffers::Offset<EnumVal> CreateEnumVal(
|
|||||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||||
int64_t value = 0,
|
int64_t value = 0,
|
||||||
flatbuffers::Offset<reflection::Type> union_type = 0,
|
flatbuffers::Offset<reflection::Type> union_type = 0,
|
||||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
|
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0,
|
||||||
|
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes = 0) {
|
||||||
EnumValBuilder builder_(_fbb);
|
EnumValBuilder builder_(_fbb);
|
||||||
builder_.add_value(value);
|
builder_.add_value(value);
|
||||||
|
builder_.add_attributes(attributes);
|
||||||
builder_.add_documentation(documentation);
|
builder_.add_documentation(documentation);
|
||||||
builder_.add_union_type(union_type);
|
builder_.add_union_type(union_type);
|
||||||
builder_.add_name(name);
|
builder_.add_name(name);
|
||||||
@@ -415,15 +427,18 @@ inline flatbuffers::Offset<EnumVal> CreateEnumValDirect(
|
|||||||
const char *name = nullptr,
|
const char *name = nullptr,
|
||||||
int64_t value = 0,
|
int64_t value = 0,
|
||||||
flatbuffers::Offset<reflection::Type> union_type = 0,
|
flatbuffers::Offset<reflection::Type> union_type = 0,
|
||||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr,
|
||||||
|
std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr) {
|
||||||
auto name__ = name ? _fbb.CreateString(name) : 0;
|
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||||
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
|
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
|
||||||
|
auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
|
||||||
return reflection::CreateEnumVal(
|
return reflection::CreateEnumVal(
|
||||||
_fbb,
|
_fbb,
|
||||||
name__,
|
name__,
|
||||||
value,
|
value,
|
||||||
union_type,
|
union_type,
|
||||||
documentation__);
|
documentation__,
|
||||||
|
attributes__);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||||
|
|||||||
@@ -27,14 +27,15 @@ struct String;
|
|||||||
|
|
||||||
// An STL compatible iterator implementation for Vector below, effectively
|
// An STL compatible iterator implementation for Vector below, effectively
|
||||||
// calling Get() for every element.
|
// calling Get() for every element.
|
||||||
template<typename T, typename IT> struct VectorIterator {
|
template<typename T, typename IT, typename Data = uint8_t *>
|
||||||
|
struct VectorIterator {
|
||||||
typedef std::random_access_iterator_tag iterator_category;
|
typedef std::random_access_iterator_tag iterator_category;
|
||||||
typedef IT value_type;
|
typedef IT value_type;
|
||||||
typedef ptrdiff_t difference_type;
|
typedef ptrdiff_t difference_type;
|
||||||
typedef IT *pointer;
|
typedef IT *pointer;
|
||||||
typedef IT &reference;
|
typedef IT &reference;
|
||||||
|
|
||||||
VectorIterator(const uint8_t *data, uoffset_t i)
|
VectorIterator(Data data, uoffset_t i)
|
||||||
: data_(data + IndirectHelper<T>::element_stride * i) {}
|
: data_(data + IndirectHelper<T>::element_stride * i) {}
|
||||||
VectorIterator(const VectorIterator &other) : data_(other.data_) {}
|
VectorIterator(const VectorIterator &other) : data_(other.data_) {}
|
||||||
VectorIterator() : data_(nullptr) {}
|
VectorIterator() : data_(nullptr) {}
|
||||||
@@ -116,9 +117,12 @@ template<typename T, typename IT> struct VectorIterator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const uint8_t *data_;
|
Data data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T, typename IT>
|
||||||
|
using VectorConstIterator = VectorIterator<T, IT, const uint8_t *>;
|
||||||
|
|
||||||
template<typename Iterator>
|
template<typename Iterator>
|
||||||
struct VectorReverseIterator : public std::reverse_iterator<Iterator> {
|
struct VectorReverseIterator : public std::reverse_iterator<Iterator> {
|
||||||
explicit VectorReverseIterator(Iterator iter)
|
explicit VectorReverseIterator(Iterator iter)
|
||||||
@@ -145,7 +149,7 @@ template<typename T> class Vector {
|
|||||||
public:
|
public:
|
||||||
typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type>
|
typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type>
|
||||||
iterator;
|
iterator;
|
||||||
typedef VectorIterator<T, typename IndirectHelper<T>::return_type>
|
typedef VectorConstIterator<T, typename IndirectHelper<T>::return_type>
|
||||||
const_iterator;
|
const_iterator;
|
||||||
typedef VectorReverseIterator<iterator> reverse_iterator;
|
typedef VectorReverseIterator<iterator> reverse_iterator;
|
||||||
typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
|
typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
|
||||||
|
|||||||
35
java/pom.xml
35
java/pom.xml
@@ -3,7 +3,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>com.google.flatbuffers</groupId>
|
<groupId>com.google.flatbuffers</groupId>
|
||||||
<artifactId>flatbuffers-java</artifactId>
|
<artifactId>flatbuffers-java</artifactId>
|
||||||
<version>22.9.24</version>
|
<version>22.10.25</version>
|
||||||
<packaging>bundle</packaging>
|
<packaging>bundle</packaging>
|
||||||
<name>FlatBuffers Java API</name>
|
<name>FlatBuffers Java API</name>
|
||||||
<description>
|
<description>
|
||||||
@@ -58,19 +58,17 @@
|
|||||||
</distributionManagement>
|
</distributionManagement>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
<release>8</release>
|
<release>8</release>
|
||||||
<testExcludes>
|
<testExcludes>
|
||||||
<testExclude>**/LongEnum.java</testExclude>
|
<testExclude>MyGame/Example/MonsterStorageGrpc.java</testExclude>
|
||||||
<testExclude>MyGame/Example/MonsterStorageGrpc.java</testExclude>
|
<testExclude>MyGame/OtherNameSpace/TableBT.java</testExclude>
|
||||||
<testExclude>MyGame/Example/StructOfStructs**</testExclude>
|
</testExcludes>
|
||||||
<testExclude>MyGame/OtherNameSpace/TableBT.java</testExclude>
|
</configuration>
|
||||||
</testExcludes>
|
<version>3.8.1</version>
|
||||||
</configuration>
|
</plugin>
|
||||||
<version>3.8.1</version>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
<profiles>
|
<profiles>
|
||||||
@@ -149,10 +147,10 @@
|
|||||||
<goal>sign</goal>
|
<goal>sign</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<gpgArguments>
|
<gpgArguments>
|
||||||
<arg>--pinentry-mode</arg>
|
<arg>--pinentry-mode</arg>
|
||||||
<arg>loopback</arg>
|
<arg>loopback</arg>
|
||||||
</gpgArguments>
|
</gpgArguments>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
@@ -173,4 +171,3 @@
|
|||||||
</profile>
|
</profile>
|
||||||
</profiles>
|
</profiles>
|
||||||
</project>
|
</project>
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public class Constants {
|
|||||||
Changes to the Java implementation need to be sure to change
|
Changes to the Java implementation need to be sure to change
|
||||||
the version here and in the code generator on every possible
|
the version here and in the code generator on every possible
|
||||||
incompatible change */
|
incompatible change */
|
||||||
public static void FLATBUFFERS_22_9_24() {}
|
public static void FLATBUFFERS_22_10_25() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @endcond
|
/// @endcond
|
||||||
|
|||||||
@@ -32,6 +32,6 @@ namespace Google.FlatBuffers
|
|||||||
Changes to the C# implementation need to be sure to change
|
Changes to the C# implementation need to be sure to change
|
||||||
the version here and in the code generator on every possible
|
the version here and in the code generator on every possible
|
||||||
incompatible change */
|
incompatible change */
|
||||||
public static void FLATBUFFERS_22_9_24() {}
|
public static void FLATBUFFERS_22_10_25() {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netstandard2.1;netstandard2.0;net46</TargetFrameworks>
|
<TargetFrameworks>netstandard2.1;netstandard2.0;net46</TargetFrameworks>
|
||||||
<Description>A cross-platform memory efficient serialization library</Description>
|
<Description>A cross-platform memory efficient serialization library</Description>
|
||||||
<PackageVersion>22.9.24</PackageVersion>
|
<PackageVersion>22.10.25</PackageVersion>
|
||||||
<Authors>Google LLC</Authors>
|
<Authors>Google LLC</Authors>
|
||||||
<PackageProjectUrl>https://github.com/google/flatbuffers</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/google/flatbuffers</PackageProjectUrl>
|
||||||
<RepositoryUrl>https://github.com/google/flatbuffers</RepositoryUrl>
|
<RepositoryUrl>https://github.com/google/flatbuffers</RepositoryUrl>
|
||||||
|
|||||||
7
nim/flatbuffers.nimble
Normal file
7
nim/flatbuffers.nimble
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
version = "2.0.8"
|
||||||
|
author = "flatbuffers"
|
||||||
|
description = "Flatbuffers"
|
||||||
|
license = "Apache 2.0"
|
||||||
|
srcDir = "flatbuffers"
|
||||||
|
|
||||||
|
requires "nim >= 1.4.0"
|
||||||
7
nim/flatbuffers/flatbuffers.nim
Normal file
7
nim/flatbuffers/flatbuffers.nim
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import
|
||||||
|
src/[
|
||||||
|
builder,
|
||||||
|
struct,
|
||||||
|
table
|
||||||
|
]
|
||||||
|
export flatbuffers.builder, flatbuffers.table, flatbuffers.struct
|
||||||
262
nim/flatbuffers/src/builder.nim
Normal file
262
nim/flatbuffers/src/builder.nim
Normal file
@@ -0,0 +1,262 @@
|
|||||||
|
import math
|
||||||
|
import table
|
||||||
|
|
||||||
|
|
||||||
|
const MAX_BUFFER_SIZE* = 2^31
|
||||||
|
|
||||||
|
|
||||||
|
type Builder* = ref object of RootObj
|
||||||
|
bytes*: seq[byte]
|
||||||
|
minalign*: int
|
||||||
|
current_vtable*: seq[uoffset]
|
||||||
|
objectEnd*: uoffset
|
||||||
|
vtables*: seq[uoffset] #?
|
||||||
|
head*: uoffset
|
||||||
|
nested*: bool
|
||||||
|
finished*: bool
|
||||||
|
vectorNumElems*: uoffset
|
||||||
|
|
||||||
|
using this: var Builder
|
||||||
|
|
||||||
|
func newBuilder*(size: int): Builder =
|
||||||
|
result = new Builder
|
||||||
|
result.bytes.setLen(size)
|
||||||
|
result.minalign = 1
|
||||||
|
result.head = size.uoffset
|
||||||
|
result.nested = false
|
||||||
|
result.finished = false
|
||||||
|
result.vectorNumElems = 0
|
||||||
|
|
||||||
|
proc FinishedBytes*(this): seq[byte] =
|
||||||
|
if not this.finished:
|
||||||
|
quit("Builder not finished, Incorrect use of FinishedBytes(): must call 'Finish' first.")
|
||||||
|
result = this.bytes[this.head..^1]
|
||||||
|
|
||||||
|
proc Output*(this): seq[byte] =
|
||||||
|
if not this.finished:
|
||||||
|
quit("Builder not finished, Incorrect use of Output(): must call 'Finish' first.")
|
||||||
|
|
||||||
|
result = this.bytes[this.head..^1]
|
||||||
|
|
||||||
|
func Offset*(this): uoffset =
|
||||||
|
result = this.bytes.len.uoffset - this.head
|
||||||
|
|
||||||
|
proc StartObject*(this; numfields: int) =
|
||||||
|
if this.nested:
|
||||||
|
quit("builder is nested")
|
||||||
|
|
||||||
|
this.current_vtable.setLen(numfields)
|
||||||
|
for i in this.current_vtable.mitems():
|
||||||
|
i = 0
|
||||||
|
this.objectEnd = this.Offset()
|
||||||
|
this.nested = true
|
||||||
|
|
||||||
|
proc GrowByteBuffer*(this) =
|
||||||
|
if this.bytes.len == MAX_BUFFER_SIZE:
|
||||||
|
quit("flatbuffers: cannot grow buffer beyond 2 gigabytes")
|
||||||
|
let oldLen = this.bytes.len
|
||||||
|
var newLen = min(this.bytes.len * 2, MAX_BUFFER_SIZE)
|
||||||
|
if newLen == 0:
|
||||||
|
newLen = 1
|
||||||
|
this.bytes.setLen(newLen)
|
||||||
|
var j = this.bytes.len - 1
|
||||||
|
while j >= 0:
|
||||||
|
if j >= newLen - oldLen:
|
||||||
|
this.bytes[j] = this.bytes[j - (newLen - oldLen)]
|
||||||
|
else:
|
||||||
|
this.bytes[j] = 0
|
||||||
|
dec(j)
|
||||||
|
|
||||||
|
proc Place*[T](this; x: T) =
|
||||||
|
this.head -= uoffset x.sizeof
|
||||||
|
WriteVal(this.bytes, this.head, x)
|
||||||
|
|
||||||
|
func Pad*(this; n: int) =
|
||||||
|
for i in 0..<n:
|
||||||
|
this.Place(0.byte)
|
||||||
|
|
||||||
|
proc Prep*(this; size: int; additionalBytes: int) =
|
||||||
|
if size > this.minalign:
|
||||||
|
this.minalign = size
|
||||||
|
var alignsize = (not (this.bytes.len - this.head.int + additionalBytes)) + 1
|
||||||
|
alignsize = alignsize and (size - 1)
|
||||||
|
|
||||||
|
while this.head.int < alignsize + size + additionalBytes:
|
||||||
|
let oldbufSize = this.bytes.len
|
||||||
|
this.GrowByteBuffer()
|
||||||
|
this.head = (this.head.int + this.bytes.len - oldbufSize).uoffset
|
||||||
|
this.Pad(alignsize)
|
||||||
|
|
||||||
|
proc PrependOffsetRelative*[T: Offsets](this; off: T) =
|
||||||
|
when T is voffset:
|
||||||
|
this.Prep(T.sizeof, 0)
|
||||||
|
if not off.uoffset <= this.Offset:
|
||||||
|
quit("flatbuffers: Offset arithmetic error.")
|
||||||
|
this.Place(off)
|
||||||
|
else:
|
||||||
|
this.Prep(T.sizeof, 0)
|
||||||
|
if not off.uoffset <= this.Offset:
|
||||||
|
quit("flatbuffers: Offset arithmetic error.")
|
||||||
|
let off2: T = this.Offset.T - off + sizeof(T).T
|
||||||
|
this.Place(off2)
|
||||||
|
|
||||||
|
|
||||||
|
proc Prepend*[T](this; x: T) =
|
||||||
|
this.Prep(x.sizeof, 0)
|
||||||
|
this.Place(x)
|
||||||
|
|
||||||
|
proc Slot*(this; slotnum: int) =
|
||||||
|
this.current_vtable[slotnum] = this.Offset
|
||||||
|
|
||||||
|
proc PrependSlot*[T](this; o: int; x, d: T) =
|
||||||
|
if x != d:
|
||||||
|
when T is uoffset or T is soffset or T is voffset:
|
||||||
|
this.PrependOffsetRelative(x)
|
||||||
|
else:
|
||||||
|
this.Prepend(x)
|
||||||
|
this.Slot(o)
|
||||||
|
|
||||||
|
proc AssertStuctInline(this; obj: uoffset) =
|
||||||
|
if obj != this.Offset:
|
||||||
|
quit("flatbuffers: Tried to write a Struct at an Offset that is different from the current Offset of the Builder.")
|
||||||
|
|
||||||
|
proc PrependStructSlot*(this; o: int; x: uoffset; d: uoffset) =
|
||||||
|
if x != d:
|
||||||
|
this.AssertStuctInline(x)
|
||||||
|
this.Slot(o)
|
||||||
|
|
||||||
|
proc Add*[T](this; n: T) =
|
||||||
|
this.Prep(T.sizeof, 0)
|
||||||
|
WriteVal(this.bytes, this.head, n)
|
||||||
|
|
||||||
|
proc VtableEqual*(a: seq[uoffset]; objectStart: uoffset; b: seq[byte]): bool =
|
||||||
|
if a.len * voffset.sizeof != b.len:
|
||||||
|
return false
|
||||||
|
|
||||||
|
var i = 0
|
||||||
|
while i < a.len:
|
||||||
|
var seq = b[i * voffset.sizeof..<(i + 1) * voffset.sizeof]
|
||||||
|
let x = GetVal[voffset](addr seq)
|
||||||
|
|
||||||
|
if x == 0 and a[i] == 0:
|
||||||
|
inc i
|
||||||
|
continue
|
||||||
|
|
||||||
|
let y = objectStart.soffset - a[i].soffset
|
||||||
|
if x.soffset != y:
|
||||||
|
return false
|
||||||
|
inc i
|
||||||
|
return true
|
||||||
|
|
||||||
|
proc WriteVtable*(this): uoffset =
|
||||||
|
this.PrependOffsetRelative(0.soffset)
|
||||||
|
|
||||||
|
let objectOffset = this.Offset
|
||||||
|
var existingVtable = uoffset 0
|
||||||
|
|
||||||
|
var i = this.current_vtable.len - 1
|
||||||
|
while i >= 0 and this.current_vtable[i] == 0: dec i
|
||||||
|
|
||||||
|
this.current_vtable = this.current_vtable[0..i]
|
||||||
|
for i in countdown(this.vtables.len - 1, 0):
|
||||||
|
let
|
||||||
|
vt2Offset: uoffset = this.vtables[i]
|
||||||
|
vt2Start: int = this.bytes.len - int vt2Offset
|
||||||
|
|
||||||
|
var seq = this.bytes[vt2Start..<this.bytes.len]
|
||||||
|
let
|
||||||
|
vt2Len = GetVal[voffset](addr seq)
|
||||||
|
metadata = 2 * voffset.sizeof # VtableMetadataFields * SizeVOffsetT
|
||||||
|
vt2End = vt2Start + vt2Len.int
|
||||||
|
vt2 = this.bytes[this.bytes.len - vt2Offset.int + metadata..<vt2End]
|
||||||
|
|
||||||
|
if VtableEqual(this.current_vtable, objectOffset, vt2):
|
||||||
|
existingVtable = vt2Offset
|
||||||
|
break
|
||||||
|
|
||||||
|
if existingVtable == 0:
|
||||||
|
for i in countdown(this.current_vtable.len - 1, 0):
|
||||||
|
var off: uoffset
|
||||||
|
if this.current_vtable[i] != 0:
|
||||||
|
off = objectOffset - this.current_vtable[i]
|
||||||
|
|
||||||
|
this.PrependOffsetRelative(off.voffset)
|
||||||
|
|
||||||
|
let objectSize = objectOffset - this.objectEnd
|
||||||
|
this.PrependOffsetRelative(objectSize.voffset)
|
||||||
|
|
||||||
|
let vBytes = (this.current_vtable.len + 2) * voffset.sizeof
|
||||||
|
this.PrependOffsetRelative(vBytes.voffset)
|
||||||
|
|
||||||
|
let objectStart: uoffset = (this.bytes.len.uoffset - objectOffset)
|
||||||
|
WriteVal(this.bytes, objectStart, (this.Offset - objectOffset).soffset)
|
||||||
|
this.vtables.add this.Offset
|
||||||
|
else:
|
||||||
|
let objectStart: uoffset = this.bytes.len.uoffset - objectOffset
|
||||||
|
this.head = objectStart
|
||||||
|
WriteVal(this.bytes, this.head,
|
||||||
|
(existingVtable.soffset - objectOffset.soffset))
|
||||||
|
|
||||||
|
this.current_vtable = @[]
|
||||||
|
result = objectOffset
|
||||||
|
|
||||||
|
proc EndObject*(this): uoffset =
|
||||||
|
if not this.nested:
|
||||||
|
quit("builder is not nested")
|
||||||
|
result = this.WriteVtable()
|
||||||
|
this.nested = false
|
||||||
|
|
||||||
|
proc End*(this: var Builder): uoffset =
|
||||||
|
result = this.EndObject()
|
||||||
|
|
||||||
|
proc StartVector*(this; elemSize: int; numElems: uoffset;
|
||||||
|
alignment: int) =
|
||||||
|
if this.nested:
|
||||||
|
quit("builder is nested")
|
||||||
|
this.nested = true
|
||||||
|
this.vectorNumElems = numElems
|
||||||
|
this.Prep(sizeof(uint32), elemSize * numElems.int)
|
||||||
|
this.Prep(alignment, elemSize * numElems.int)
|
||||||
|
|
||||||
|
proc EndVector*(this): uoffset =
|
||||||
|
if not this.nested:
|
||||||
|
quit("builder is not nested")
|
||||||
|
this.nested = false
|
||||||
|
this.Place(this.vectorNumElems)
|
||||||
|
this.vectorNumElems = 0
|
||||||
|
result = this.Offset
|
||||||
|
|
||||||
|
proc getChars*(str: seq[byte]): string =
|
||||||
|
var bytes = str
|
||||||
|
result = GetVal[string](addr bytes)
|
||||||
|
|
||||||
|
proc getBytes*(str: string | cstring): seq[byte] =
|
||||||
|
for chr in str:
|
||||||
|
result.add byte chr
|
||||||
|
result.add byte 0
|
||||||
|
|
||||||
|
proc Create*[T](this; s: T): uoffset = # Both CreateString and CreateByteVector functionality
|
||||||
|
if this.nested:
|
||||||
|
quit("builder is nested")
|
||||||
|
this.nested = true
|
||||||
|
when T is cstring or T is string:
|
||||||
|
let x = s.getBytes()
|
||||||
|
let l = x.len.uoffset
|
||||||
|
this.vectorNumElems = l-1
|
||||||
|
else:
|
||||||
|
let x = s
|
||||||
|
let l = x.len.uoffset
|
||||||
|
this.vectorNumElems = l
|
||||||
|
this.Prep(uoffset.sizeof, l.int * byte.sizeof)
|
||||||
|
this.head -= l
|
||||||
|
this.bytes[this.head..<this.head+l] = x
|
||||||
|
result = this.EndVector()
|
||||||
|
|
||||||
|
proc Finish*(this; rootTable: uoffset) =
|
||||||
|
if this.nested:
|
||||||
|
quit("builder is nested")
|
||||||
|
this.nested = true
|
||||||
|
|
||||||
|
this.Prep(this.minalign, uoffset.sizeof)
|
||||||
|
this.PrependOffsetRelative(rootTable)
|
||||||
|
this.finished = true
|
||||||
12
nim/flatbuffers/src/endian.nim
Normal file
12
nim/flatbuffers/src/endian.nim
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
template swapEndian*(outp, inp: pointer, size: int) =
|
||||||
|
var i = cast[cstring](inp)
|
||||||
|
var o = cast[cstring](outp)
|
||||||
|
for x in 0..<size:
|
||||||
|
o[x] = i[(0..<size).len - x - 1]
|
||||||
|
|
||||||
|
when system.cpuEndian == bigEndian:
|
||||||
|
func littleEndianX*(outp, inp: pointer, size: int) {.inline.} = swapEndian(outp, inp, size)
|
||||||
|
func bigEndianX*(outp, inp: pointer, size: int) {.inline.} = copyMem(outp, inp, size)
|
||||||
|
else:
|
||||||
|
func littleEndianX*(outp, inp: pointer, size: int) {.inline.} = copyMem(outp, inp, size)
|
||||||
|
func bigEndianX*(outp, inp: pointer, size: int) {.inline.} = swapEndian(outp, inp, size)
|
||||||
24
nim/flatbuffers/src/struct.nim
Normal file
24
nim/flatbuffers/src/struct.nim
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import table
|
||||||
|
|
||||||
|
|
||||||
|
type FlatObj* {.inheritable.} = object
|
||||||
|
tab*: Vtable
|
||||||
|
|
||||||
|
func Table*(this: var FlatObj): Vtable = this.tab
|
||||||
|
|
||||||
|
func Init*(this: var FlatObj; buf: seq[byte]; i: uoffset) =
|
||||||
|
this.tab.Bytes = buf
|
||||||
|
this.tab.Pos = i
|
||||||
|
|
||||||
|
# Cant define it in table.nim since it needs FlatObj and Init
|
||||||
|
func GetUnion*[T: FlatObj](this: var Vtable; off: uoffset): T =
|
||||||
|
result.Init(this.Bytes, this.Indirect(off))
|
||||||
|
|
||||||
|
func GetRootAs*(result: var FlatObj; buf: seq[byte]; offset: uoffset) =
|
||||||
|
var
|
||||||
|
vtable = Vtable(Bytes: buf[offset..^1], Pos: offset)
|
||||||
|
n = Get[uoffset](vtable, offset)
|
||||||
|
result.Init(buf, n+offset)
|
||||||
|
|
||||||
|
func GetRootAs*(result: var FlatObj; buf: string; offset: uoffset) =
|
||||||
|
result.GetRootAs(cast[seq[byte]](buf), offset)
|
||||||
149
nim/flatbuffers/src/table.nim
Normal file
149
nim/flatbuffers/src/table.nim
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
import endian
|
||||||
|
|
||||||
|
|
||||||
|
type
|
||||||
|
uoffset* = uint32 ## offset in to the buffer
|
||||||
|
soffset* = int32 ## offset from start of table, to a vtable
|
||||||
|
voffset* = uint16 ## offset from start of table to value
|
||||||
|
|
||||||
|
type Offsets* = uoffset | soffset | voffset
|
||||||
|
|
||||||
|
type Vtable* = object
|
||||||
|
Bytes*: seq[byte]
|
||||||
|
Pos*: uoffset
|
||||||
|
|
||||||
|
|
||||||
|
using this: Vtable
|
||||||
|
|
||||||
|
|
||||||
|
func GetVal*[T](b: ptr seq[byte]): T {.inline.} =
|
||||||
|
when T is float64:
|
||||||
|
result = cast[T](GetVal[uint64](b))
|
||||||
|
elif T is float32:
|
||||||
|
result = cast[T](GetVal[uint32](b))
|
||||||
|
elif T is string:
|
||||||
|
result = cast[T](b[])
|
||||||
|
else:
|
||||||
|
if b[].len < T.sizeof:
|
||||||
|
b[].setLen T.sizeof
|
||||||
|
result = cast[ptr T](unsafeAddr b[][0])[]
|
||||||
|
|
||||||
|
|
||||||
|
template Get*[T](this; off: uoffset): T =
|
||||||
|
var seq = this.Bytes[off..^1]
|
||||||
|
GetVal[T](addr seq)
|
||||||
|
|
||||||
|
template Get*[T](this; off: soffset): T =
|
||||||
|
var seq = this.Bytes[off..^1]
|
||||||
|
GetVal[T](addr seq)
|
||||||
|
|
||||||
|
template Get*[T](this; off: voffset): T =
|
||||||
|
var seq = this.Bytes[off..^1]
|
||||||
|
GetVal[T](addr seq)
|
||||||
|
|
||||||
|
func WriteVal*[T: not SomeFloat](b: var openArray[byte]; off: uoffset;
|
||||||
|
n: T) {.inline.} =
|
||||||
|
when sizeof(T) == 8:
|
||||||
|
littleEndianX(addr b[off], unsafeAddr n, T.sizeof)
|
||||||
|
elif sizeof(T) == 4:
|
||||||
|
littleEndianX(addr b[off], unsafeAddr n, T.sizeof)
|
||||||
|
elif sizeof(T) == 2:
|
||||||
|
littleEndianX(addr b[off], unsafeAddr n, T.sizeof)
|
||||||
|
elif sizeof(T) == 1:
|
||||||
|
b[off] = n.uint8
|
||||||
|
else:
|
||||||
|
discard
|
||||||
|
#littleEndianX(addr b[off], unsafeAddr n, T.sizeof)
|
||||||
|
#{.error:"shouldnt appear".}
|
||||||
|
|
||||||
|
func WriteVal*[T: not SomeFloat](b: var seq[byte]; off: uoffset;
|
||||||
|
n: T) {.inline.} =
|
||||||
|
when sizeof(T) == 8:
|
||||||
|
littleEndianX(addr b[off], unsafeAddr n, T.sizeof)
|
||||||
|
elif sizeof(T) == 4:
|
||||||
|
littleEndianX(addr b[off], unsafeAddr n, T.sizeof)
|
||||||
|
elif sizeof(T) == 2:
|
||||||
|
littleEndianX(addr b[off], unsafeAddr n, T.sizeof)
|
||||||
|
elif sizeof(T) == 1:
|
||||||
|
b[off] = n.uint8
|
||||||
|
else:
|
||||||
|
discard
|
||||||
|
#littleEndianX(addr b[off], unsafeAddr n, T.sizeof)
|
||||||
|
#{.error:"shouldnt appear".}
|
||||||
|
|
||||||
|
func WriteVal*[T: SomeFloat](b: var openArray[byte]; off: uoffset;
|
||||||
|
n: T) {.inline.} =
|
||||||
|
when T is float64:
|
||||||
|
WriteVal(b, off, cast[uint64](n))
|
||||||
|
elif T is float32:
|
||||||
|
WriteVal(b, off, cast[uint32](n))
|
||||||
|
|
||||||
|
func WriteVal*[T: SomeFloat](b: var seq[byte]; off: uoffset; n: T) {.inline.} =
|
||||||
|
when T is float64:
|
||||||
|
WriteVal(b, off, cast[uint64](n))
|
||||||
|
elif T is float32:
|
||||||
|
WriteVal(b, off, cast[uint32](n))
|
||||||
|
|
||||||
|
func Offset*(this; off: voffset): voffset =
|
||||||
|
let vtable = (this.Pos - this.Get[:uoffset](this.Pos)).voffset
|
||||||
|
let vtableEnd = this.Get[:voffset](vtable)
|
||||||
|
if off < vtableEnd:
|
||||||
|
return this.Get[:voffset](vtable + off)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
func Indirect*(this; off: uoffset): uoffset =
|
||||||
|
result = off + this.Get[:uoffset](off)
|
||||||
|
|
||||||
|
func VectorLen*(this; off: uoffset): int =
|
||||||
|
var newoff: uoffset = off + this.Pos
|
||||||
|
newoff += this.Get[:uoffset](newoff)
|
||||||
|
return this.Get[:uoffset](newoff).int
|
||||||
|
|
||||||
|
func Vector*(this; off: uoffset): uoffset =
|
||||||
|
let newoff: uoffset = off + this.Pos
|
||||||
|
var x: uoffset = newoff + this.Get[:uoffset](newoff)
|
||||||
|
x += (uoffset.sizeof).uoffset
|
||||||
|
result = x
|
||||||
|
|
||||||
|
func Union*(this; off: uoffset): Vtable =
|
||||||
|
let newoff: uoffset = off + this.Pos
|
||||||
|
result.Pos = newoff + this.Get[:uoffset](newoff)
|
||||||
|
result.Bytes = this.Bytes
|
||||||
|
|
||||||
|
func GetSlot*[T](this; slot: voffset; d: T): T =
|
||||||
|
let off = this.Offset(slot)
|
||||||
|
if off == 0:
|
||||||
|
return d
|
||||||
|
return this.Get[T](this.Pos + off)
|
||||||
|
|
||||||
|
func GetOffsetSlot*[T: Offsets](this; slot: voffset; d: T): T =
|
||||||
|
let off = this.Offset(slot)
|
||||||
|
if off == 0:
|
||||||
|
return d
|
||||||
|
return off
|
||||||
|
|
||||||
|
func ByteVector*(this; off: uoffset): seq[byte] =
|
||||||
|
let
|
||||||
|
newoff: uoffset = off + this.Get[:uoffset](off)
|
||||||
|
start = newoff + (uoffset.sizeof).uoffset
|
||||||
|
var newseq = this.Bytes[newoff..^1]
|
||||||
|
let
|
||||||
|
length = GetVal[uoffset](addr newseq)
|
||||||
|
result = this.Bytes[start..<start+length]
|
||||||
|
|
||||||
|
func String*(this; off: uoffset): string =
|
||||||
|
var byte_seq = this.ByteVector(off)
|
||||||
|
result = GetVal[string](addr byte_seq)
|
||||||
|
|
||||||
|
using this: var Vtable
|
||||||
|
|
||||||
|
proc Mutate*[T](this; off: uoffset; n: T): bool =
|
||||||
|
WriteVal(this.Bytes, off, n)
|
||||||
|
return true
|
||||||
|
|
||||||
|
func MutateSlot*[T](this; slot: voffset; n: T): bool =
|
||||||
|
let off: voffset = this.Offset(slot)
|
||||||
|
if off != 0:
|
||||||
|
return this.Mutate(this.Pos + off.uoffset, n)
|
||||||
|
return false
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "flatbuffers",
|
"name": "flatbuffers",
|
||||||
"version": "22.9.24",
|
"version": "22.10.25",
|
||||||
"description": "Memory Efficient Serialization Library",
|
"description": "Memory Efficient Serialization Library",
|
||||||
"files": [
|
"files": [
|
||||||
"js/**/*.js",
|
"js/**/*.js",
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "npm run compile && cd tests/ts && python3 ./TypeScriptTest.py",
|
"test": "npm run compile && cd tests/ts && python3 ./TypeScriptTest.py",
|
||||||
|
"lint": "eslint ts",
|
||||||
"compile": "tsc && tsc -p tsconfig.mjs.json && rollup -c",
|
"compile": "tsc && tsc -p tsconfig.mjs.json && rollup -c",
|
||||||
"prepublishOnly": "npm install --only=dev && npm run compile"
|
"prepublishOnly": "npm install --only=dev && npm run compile"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -14,4 +14,4 @@
|
|||||||
|
|
||||||
# Placeholder, to be updated during the release process
|
# Placeholder, to be updated during the release process
|
||||||
# by the setup.py
|
# by the setup.py
|
||||||
__version__ = u"22.9.24"
|
__version__ = u"22.10.25"
|
||||||
|
|||||||
@@ -73,7 +73,32 @@ class EnumVal(object):
|
|||||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
|
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
|
||||||
return o == 0
|
return o == 0
|
||||||
|
|
||||||
def EnumValStart(builder): builder.StartObject(5)
|
# EnumVal
|
||||||
|
def Attributes(self, j):
|
||||||
|
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
|
||||||
|
if o != 0:
|
||||||
|
x = self._tab.Vector(o)
|
||||||
|
x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
|
||||||
|
x = self._tab.Indirect(x)
|
||||||
|
from reflection.KeyValue import KeyValue
|
||||||
|
obj = KeyValue()
|
||||||
|
obj.Init(self._tab.Bytes, x)
|
||||||
|
return obj
|
||||||
|
return None
|
||||||
|
|
||||||
|
# EnumVal
|
||||||
|
def AttributesLength(self):
|
||||||
|
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
|
||||||
|
if o != 0:
|
||||||
|
return self._tab.VectorLen(o)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# EnumVal
|
||||||
|
def AttributesIsNone(self):
|
||||||
|
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
|
||||||
|
return o == 0
|
||||||
|
|
||||||
|
def EnumValStart(builder): builder.StartObject(6)
|
||||||
def Start(builder):
|
def Start(builder):
|
||||||
return EnumValStart(builder)
|
return EnumValStart(builder)
|
||||||
def EnumValAddName(builder, name): builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(name), 0)
|
def EnumValAddName(builder, name): builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(name), 0)
|
||||||
@@ -91,6 +116,12 @@ def AddDocumentation(builder, documentation):
|
|||||||
def EnumValStartDocumentationVector(builder, numElems): return builder.StartVector(4, numElems, 4)
|
def EnumValStartDocumentationVector(builder, numElems): return builder.StartVector(4, numElems, 4)
|
||||||
def StartDocumentationVector(builder, numElems):
|
def StartDocumentationVector(builder, numElems):
|
||||||
return EnumValStartDocumentationVector(builder, numElems)
|
return EnumValStartDocumentationVector(builder, numElems)
|
||||||
|
def EnumValAddAttributes(builder, attributes): builder.PrependUOffsetTRelativeSlot(5, flatbuffers.number_types.UOffsetTFlags.py_type(attributes), 0)
|
||||||
|
def AddAttributes(builder, attributes):
|
||||||
|
return EnumValAddAttributes(builder, attributes)
|
||||||
|
def EnumValStartAttributesVector(builder, numElems): return builder.StartVector(4, numElems, 4)
|
||||||
|
def StartAttributesVector(builder, numElems):
|
||||||
|
return EnumValStartAttributesVector(builder, numElems)
|
||||||
def EnumValEnd(builder): return builder.EndObject()
|
def EnumValEnd(builder): return builder.EndObject()
|
||||||
def End(builder):
|
def End(builder):
|
||||||
return EnumValEnd(builder)
|
return EnumValEnd(builder)
|
||||||
@@ -56,6 +56,7 @@ table EnumVal {
|
|||||||
object:Object (deprecated);
|
object:Object (deprecated);
|
||||||
union_type:Type;
|
union_type:Type;
|
||||||
documentation:[string];
|
documentation:[string];
|
||||||
|
attributes:[KeyValue];
|
||||||
}
|
}
|
||||||
|
|
||||||
table Enum {
|
table Enum {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "flatbuffers"
|
name = "flatbuffers"
|
||||||
version = "2.1.2"
|
version = "22.9.29"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
authors = ["Robert Winslow <hello@rwinslow.com>", "FlatBuffers Maintainers"]
|
authors = ["Robert Winslow <hello@rwinslow.com>", "FlatBuffers Maintainers"]
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
@@ -12,15 +12,13 @@ categories = ["encoding", "data-structures", "memory-management"]
|
|||||||
rust = "1.51"
|
rust = "1.51"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["thiserror"]
|
default = ["std"]
|
||||||
no_std = ["core2", "thiserror_core2"]
|
std = []
|
||||||
serialize = ["serde"]
|
serialize = ["serde"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
smallvec = "1.6.1"
|
|
||||||
bitflags = "1.2.1"
|
bitflags = "1.2.1"
|
||||||
serde = { version = "1.0", optional = true }
|
serde = { version = "1.0", optional = true }
|
||||||
thiserror = { version = "1.0.30", optional = true }
|
|
||||||
core2 = { version = "0.4.0", optional = true }
|
[build-dependencies]
|
||||||
# This version is compliant with mainline 1.0.30
|
rustc_version = "0.4.0"
|
||||||
thiserror_core2 = { version = "2.0.0", default-features = false, optional = true }
|
|
||||||
|
|||||||
12
rust/flatbuffers/build.rs
Normal file
12
rust/flatbuffers/build.rs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
use rustc_version::{version_meta, Channel};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let version_meta = version_meta().unwrap();
|
||||||
|
|
||||||
|
// To use nightly features we declare this and then we can use
|
||||||
|
// #[cfg(nightly)]
|
||||||
|
// for nightly only features
|
||||||
|
if version_meta.channel == Channel::Nightly {
|
||||||
|
println!("cargo:rustc-cfg=nightly")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,14 +37,18 @@ where
|
|||||||
#[allow(clippy::len_without_is_empty)]
|
#[allow(clippy::len_without_is_empty)]
|
||||||
#[allow(clippy::from_over_into)] // TODO(caspern): Go from From to Into.
|
#[allow(clippy::from_over_into)] // TODO(caspern): Go from From to Into.
|
||||||
impl<'a, T: 'a, const N: usize> Array<'a, T, N> {
|
impl<'a, T: 'a, const N: usize> Array<'a, T, N> {
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// buf must be a contiguous array of `T`
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if `buf.len()` is not `size_of::<T>() * N`
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn new(buf: &'a [u8]) -> Self {
|
pub unsafe fn new(buf: &'a [u8]) -> Self {
|
||||||
assert!(size_of::<T>() * N == buf.len());
|
assert_eq!(size_of::<T>() * N, buf.len());
|
||||||
|
|
||||||
Array {
|
Array(buf, PhantomData)
|
||||||
0: buf,
|
|
||||||
1: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -61,34 +65,39 @@ impl<'a, T: Follow<'a> + 'a, const N: usize> Array<'a, T, N> {
|
|||||||
pub fn get(&self, idx: usize) -> T::Inner {
|
pub fn get(&self, idx: usize) -> T::Inner {
|
||||||
assert!(idx < N);
|
assert!(idx < N);
|
||||||
let sz = size_of::<T>();
|
let sz = size_of::<T>();
|
||||||
T::follow(self.0, sz * idx)
|
// Safety:
|
||||||
|
// self.0 was valid for length `N` on construction and have verified `idx < N`
|
||||||
|
unsafe { T::follow(self.0, sz * idx) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn iter(&self) -> VectorIter<'a, T> {
|
pub fn iter(&self) -> VectorIter<'a, T> {
|
||||||
VectorIter::from_slice(self.0, self.len())
|
// Safety:
|
||||||
|
// self.0 was valid for length N on construction
|
||||||
|
unsafe { VectorIter::from_slice(self.0, self.len()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Follow<'a> + Debug, const N: usize> Into<[T::Inner; N]> for Array<'a, T, N> {
|
impl<'a, T: Follow<'a> + Debug, const N: usize> From<Array<'a, T, N>> for [T::Inner; N] {
|
||||||
#[inline(always)]
|
fn from(array: Array<'a, T, N>) -> Self {
|
||||||
fn into(self) -> [T::Inner; N] {
|
array_init(|i| array.get(i))
|
||||||
array_init(|i| self.get(i))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(caspern): Implement some future safe version of SafeSliceAccess.
|
|
||||||
|
|
||||||
/// Implement Follow for all possible Arrays that have Follow-able elements.
|
/// Implement Follow for all possible Arrays that have Follow-able elements.
|
||||||
impl<'a, T: Follow<'a> + 'a, const N: usize> Follow<'a> for Array<'a, T, N> {
|
impl<'a, T: Follow<'a> + 'a, const N: usize> Follow<'a> for Array<'a, T, N> {
|
||||||
type Inner = Array<'a, T, N>;
|
type Inner = Array<'a, T, N>;
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||||
Array::new(&buf[loc..loc + N * size_of::<T>()])
|
Array::new(&buf[loc..loc + N * size_of::<T>()])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn emplace_scalar_array<T: EndianScalar, const N: usize>(
|
/// Place an array of EndianScalar into the provided mutable byte slice. Performs
|
||||||
|
/// endian conversion, if necessary.
|
||||||
|
/// # Safety
|
||||||
|
/// Caller must ensure `s.len() >= size_of::<[T; N]>()`
|
||||||
|
pub unsafe fn emplace_scalar_array<T: EndianScalar, const N: usize>(
|
||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
loc: usize,
|
loc: usize,
|
||||||
src: &[T; N],
|
src: &[T; N],
|
||||||
@@ -96,14 +105,12 @@ pub fn emplace_scalar_array<T: EndianScalar, const N: usize>(
|
|||||||
let mut buf_ptr = buf[loc..].as_mut_ptr();
|
let mut buf_ptr = buf[loc..].as_mut_ptr();
|
||||||
for item in src.iter() {
|
for item in src.iter() {
|
||||||
let item_le = item.to_little_endian();
|
let item_le = item.to_little_endian();
|
||||||
unsafe {
|
core::ptr::copy_nonoverlapping(
|
||||||
core::ptr::copy_nonoverlapping(
|
&item_le as *const T::Scalar as *const u8,
|
||||||
&item_le as *const T as *const u8,
|
buf_ptr,
|
||||||
buf_ptr,
|
size_of::<T::Scalar>(),
|
||||||
size_of::<T>(),
|
);
|
||||||
);
|
buf_ptr = buf_ptr.add(size_of::<T::Scalar>());
|
||||||
buf_ptr = buf_ptr.add(size_of::<T>());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,6 +131,8 @@ where
|
|||||||
let mut array: core::mem::MaybeUninit<[T; N]> = core::mem::MaybeUninit::uninit();
|
let mut array: core::mem::MaybeUninit<[T; N]> = core::mem::MaybeUninit::uninit();
|
||||||
let mut ptr_i = array.as_mut_ptr() as *mut T;
|
let mut ptr_i = array.as_mut_ptr() as *mut T;
|
||||||
|
|
||||||
|
// Safety:
|
||||||
|
// array is aligned by T, and has length N
|
||||||
unsafe {
|
unsafe {
|
||||||
for i in 0..N {
|
for i in 0..N {
|
||||||
let value_i = initializer(i);
|
let value_i = initializer(i);
|
||||||
@@ -134,7 +143,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature="serialize")]
|
#[cfg(feature = "serialize")]
|
||||||
impl<'a, T: 'a, const N: usize> serde::ser::Serialize for Array<'a, T, N>
|
impl<'a, T: 'a, const N: usize> serde::ser::Serialize for Array<'a, T, N>
|
||||||
where
|
where
|
||||||
T: 'a + Follow<'a>,
|
T: 'a + Follow<'a>,
|
||||||
|
|||||||
@@ -14,26 +14,22 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern crate smallvec;
|
#[cfg(not(feature = "std"))]
|
||||||
|
use alloc::{vec, vec::Vec};
|
||||||
use core::cmp::max;
|
use core::cmp::max;
|
||||||
use core::iter::{DoubleEndedIterator, ExactSizeIterator};
|
use core::iter::{DoubleEndedIterator, ExactSizeIterator};
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::ptr::write_bytes;
|
use core::ptr::write_bytes;
|
||||||
use core::slice::from_raw_parts;
|
|
||||||
#[cfg(feature = "no_std")]
|
|
||||||
use alloc::{vec, vec::Vec};
|
|
||||||
|
|
||||||
use crate::endian_scalar::{emplace_scalar, read_scalar_at};
|
use crate::endian_scalar::emplace_scalar;
|
||||||
use crate::primitives::*;
|
use crate::primitives::*;
|
||||||
use crate::push::{Push, PushAlignment};
|
use crate::push::{Push, PushAlignment};
|
||||||
|
use crate::read_scalar;
|
||||||
use crate::table::Table;
|
use crate::table::Table;
|
||||||
use crate::vector::{SafeSliceAccess, Vector};
|
use crate::vector::Vector;
|
||||||
use crate::vtable::{field_index_to_field_offset, VTable};
|
use crate::vtable::{field_index_to_field_offset, VTable};
|
||||||
use crate::vtable_writer::VTableWriter;
|
use crate::vtable_writer::VTableWriter;
|
||||||
|
|
||||||
pub const N_SMALLVEC_STRING_VECTOR_CAPACITY: usize = 16;
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
struct FieldLoc {
|
struct FieldLoc {
|
||||||
off: UOffsetT,
|
off: UOffsetT,
|
||||||
@@ -120,7 +116,9 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
|
|||||||
// memset only the part of the buffer that could be dirty:
|
// memset only the part of the buffer that could be dirty:
|
||||||
{
|
{
|
||||||
let to_clear = self.owned_buf.len() - self.head;
|
let to_clear = self.owned_buf.len() - self.head;
|
||||||
let ptr = (&mut self.owned_buf[self.head..]).as_mut_ptr();
|
let ptr = self.owned_buf[self.head..].as_mut_ptr();
|
||||||
|
// Safety:
|
||||||
|
// Verified ptr is valid for `to_clear` above
|
||||||
unsafe {
|
unsafe {
|
||||||
write_bytes(ptr, 0, to_clear);
|
write_bytes(ptr, 0, to_clear);
|
||||||
}
|
}
|
||||||
@@ -152,8 +150,10 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
|
|||||||
self.align(sz, P::alignment());
|
self.align(sz, P::alignment());
|
||||||
self.make_space(sz);
|
self.make_space(sz);
|
||||||
{
|
{
|
||||||
let (dst, rest) = (&mut self.owned_buf[self.head..]).split_at_mut(sz);
|
let (dst, rest) = self.owned_buf[self.head..].split_at_mut(sz);
|
||||||
x.push(dst, rest);
|
// Safety:
|
||||||
|
// Called make_space above
|
||||||
|
unsafe { x.push(dst, rest.len()) };
|
||||||
}
|
}
|
||||||
WIPOffset::new(self.used_space() as UOffsetT)
|
WIPOffset::new(self.used_space() as UOffsetT)
|
||||||
}
|
}
|
||||||
@@ -309,73 +309,32 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
|
|||||||
WIPOffset::new(self.used_space() as UOffsetT)
|
WIPOffset::new(self.used_space() as UOffsetT)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a vector by memcpy'ing. This is much faster than calling
|
|
||||||
/// `create_vector`, but the underlying type must be represented as
|
|
||||||
/// little-endian on the host machine. This property is encoded in the
|
|
||||||
/// type system through the SafeSliceAccess trait. The following types are
|
|
||||||
/// always safe, on any platform: bool, u8, i8, and any
|
|
||||||
/// FlatBuffers-generated struct.
|
|
||||||
#[inline]
|
|
||||||
pub fn create_vector_direct<'a: 'b, 'b, T: SafeSliceAccess + Push + Sized + 'b>(
|
|
||||||
&'a mut self,
|
|
||||||
items: &'b [T],
|
|
||||||
) -> WIPOffset<Vector<'fbb, T>> {
|
|
||||||
self.assert_not_nested(
|
|
||||||
"create_vector_direct can not be called when a table or vector is under construction",
|
|
||||||
);
|
|
||||||
let elem_size = T::size();
|
|
||||||
self.align(items.len() * elem_size, T::alignment().max_of(SIZE_UOFFSET));
|
|
||||||
|
|
||||||
let bytes = {
|
|
||||||
let ptr = items.as_ptr() as *const T as *const u8;
|
|
||||||
unsafe { from_raw_parts(ptr, items.len() * elem_size) }
|
|
||||||
};
|
|
||||||
self.push_bytes_unprefixed(bytes);
|
|
||||||
self.push(items.len() as UOffsetT);
|
|
||||||
|
|
||||||
WIPOffset::new(self.used_space() as UOffsetT)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a vector of strings.
|
|
||||||
///
|
|
||||||
/// Speed-sensitive users may wish to reduce memory usage by creating the
|
|
||||||
/// vector manually: use `start_vector`, `push`, and `end_vector`.
|
|
||||||
#[inline]
|
|
||||||
pub fn create_vector_of_strings<'a, 'b>(
|
|
||||||
&'a mut self,
|
|
||||||
xs: &'b [&'b str],
|
|
||||||
) -> WIPOffset<Vector<'fbb, ForwardsUOffset<&'fbb str>>> {
|
|
||||||
self.assert_not_nested("create_vector_of_strings can not be called when a table or vector is under construction");
|
|
||||||
// internally, smallvec can be a stack-allocated or heap-allocated vector:
|
|
||||||
// if xs.len() > N_SMALLVEC_STRING_VECTOR_CAPACITY then it will overflow to the heap.
|
|
||||||
let mut offsets: smallvec::SmallVec<[WIPOffset<&str>; N_SMALLVEC_STRING_VECTOR_CAPACITY]> =
|
|
||||||
smallvec::SmallVec::with_capacity(xs.len());
|
|
||||||
unsafe {
|
|
||||||
offsets.set_len(xs.len());
|
|
||||||
}
|
|
||||||
|
|
||||||
// note that this happens in reverse, because the buffer is built back-to-front:
|
|
||||||
for (i, &s) in xs.iter().enumerate().rev() {
|
|
||||||
let o = self.create_string(s);
|
|
||||||
offsets[i] = o;
|
|
||||||
}
|
|
||||||
self.create_vector(&offsets[..])
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a vector of Push-able objects.
|
/// Create a vector of Push-able objects.
|
||||||
///
|
///
|
||||||
/// Speed-sensitive users may wish to reduce memory usage by creating the
|
/// Speed-sensitive users may wish to reduce memory usage by creating the
|
||||||
/// vector manually: use `start_vector`, `push`, and `end_vector`.
|
/// vector manually: use `start_vector`, `push`, and `end_vector`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn create_vector<'a: 'b, 'b, T: Push + Copy + 'b>(
|
pub fn create_vector<'a: 'b, 'b, T: Push + 'b>(
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
items: &'b [T],
|
items: &'b [T],
|
||||||
) -> WIPOffset<Vector<'fbb, T::Output>> {
|
) -> WIPOffset<Vector<'fbb, T::Output>> {
|
||||||
let elem_size = T::size();
|
let elem_size = T::size();
|
||||||
self.align(items.len() * elem_size, T::alignment().max_of(SIZE_UOFFSET));
|
let slice_size = items.len() * elem_size;
|
||||||
for i in (0..items.len()).rev() {
|
self.align(slice_size, T::alignment().max_of(SIZE_UOFFSET));
|
||||||
self.push(items[i]);
|
self.ensure_capacity(slice_size + UOffsetT::size());
|
||||||
|
|
||||||
|
self.head -= slice_size;
|
||||||
|
let mut written_len = self.owned_buf.len() - self.head;
|
||||||
|
|
||||||
|
let buf = &mut self.owned_buf[self.head..self.head + slice_size];
|
||||||
|
for (item, out) in items.iter().zip(buf.chunks_exact_mut(elem_size)) {
|
||||||
|
written_len -= elem_size;
|
||||||
|
|
||||||
|
// Safety:
|
||||||
|
// Called ensure_capacity and aligned to T above
|
||||||
|
unsafe { item.push(out, written_len) };
|
||||||
}
|
}
|
||||||
|
|
||||||
WIPOffset::new(self.push::<UOffsetT>(items.len() as UOffsetT).value())
|
WIPOffset::new(self.push::<UOffsetT>(items.len() as UOffsetT).value())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,17 +343,18 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
|
|||||||
/// Speed-sensitive users may wish to reduce memory usage by creating the
|
/// Speed-sensitive users may wish to reduce memory usage by creating the
|
||||||
/// vector manually: use `start_vector`, `push`, and `end_vector`.
|
/// vector manually: use `start_vector`, `push`, and `end_vector`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn create_vector_from_iter<T: Push + Copy>(
|
pub fn create_vector_from_iter<T: Push>(
|
||||||
&mut self,
|
&mut self,
|
||||||
items: impl ExactSizeIterator<Item = T> + DoubleEndedIterator,
|
items: impl ExactSizeIterator<Item = T> + DoubleEndedIterator,
|
||||||
) -> WIPOffset<Vector<'fbb, T::Output>> {
|
) -> WIPOffset<Vector<'fbb, T::Output>> {
|
||||||
let elem_size = T::size();
|
let elem_size = T::size();
|
||||||
let len = items.len();
|
self.align(items.len() * elem_size, T::alignment().max_of(SIZE_UOFFSET));
|
||||||
self.align(len * elem_size, T::alignment().max_of(SIZE_UOFFSET));
|
let mut actual = 0;
|
||||||
for item in items.rev() {
|
for item in items.rev() {
|
||||||
self.push(item);
|
self.push(item);
|
||||||
|
actual += 1;
|
||||||
}
|
}
|
||||||
WIPOffset::new(self.push::<UOffsetT>(len as UOffsetT).value())
|
WIPOffset::new(self.push::<UOffsetT>(actual).value())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set whether default values are stored.
|
/// Set whether default values are stored.
|
||||||
@@ -443,7 +403,15 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
|
|||||||
assert_msg_name: &'static str,
|
assert_msg_name: &'static str,
|
||||||
) {
|
) {
|
||||||
let idx = self.used_space() - tab_revloc.value() as usize;
|
let idx = self.used_space() - tab_revloc.value() as usize;
|
||||||
let tab = Table::new(&self.owned_buf[self.head..], idx);
|
|
||||||
|
// Safety:
|
||||||
|
// The value of TableFinishedWIPOffset is the offset from the end of owned_buf
|
||||||
|
// to an SOffsetT pointing to a valid VTable
|
||||||
|
//
|
||||||
|
// `self.owned_buf.len() = self.used_space() + self.head`
|
||||||
|
// `self.owned_buf.len() - tab_revloc = self.used_space() - tab_revloc + self.head`
|
||||||
|
// `self.owned_buf.len() - tab_revloc = idx + self.head`
|
||||||
|
let tab = unsafe { Table::new(&self.owned_buf[self.head..], idx) };
|
||||||
let o = tab.vtable().get(slot_byte_loc) as usize;
|
let o = tab.vtable().get(slot_byte_loc) as usize;
|
||||||
assert!(o != 0, "missing required field {}", assert_msg_name);
|
assert!(o != 0, "missing required field {}", assert_msg_name);
|
||||||
}
|
}
|
||||||
@@ -560,11 +528,15 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let new_vt_bytes = &self.owned_buf[vt_start_pos..vt_end_pos];
|
let new_vt_bytes = &self.owned_buf[vt_start_pos..vt_end_pos];
|
||||||
let found = self.written_vtable_revpos.binary_search_by(|old_vtable_revpos: &UOffsetT| {
|
let found = self
|
||||||
let old_vtable_pos = self.owned_buf.len() - *old_vtable_revpos as usize;
|
.written_vtable_revpos
|
||||||
let old_vtable = VTable::init(&self.owned_buf, old_vtable_pos);
|
.binary_search_by(|old_vtable_revpos: &UOffsetT| {
|
||||||
new_vt_bytes.cmp(old_vtable.as_bytes())
|
let old_vtable_pos = self.owned_buf.len() - *old_vtable_revpos as usize;
|
||||||
});
|
// Safety:
|
||||||
|
// Already written vtables are valid by construction
|
||||||
|
let old_vtable = unsafe { VTable::init(&self.owned_buf, old_vtable_pos) };
|
||||||
|
new_vt_bytes.cmp(old_vtable.as_bytes())
|
||||||
|
});
|
||||||
let final_vtable_revpos = match found {
|
let final_vtable_revpos = match found {
|
||||||
Ok(i) => {
|
Ok(i) => {
|
||||||
// The new vtable is a duplicate so clear it.
|
// The new vtable is a duplicate so clear it.
|
||||||
@@ -581,12 +553,22 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
|
|||||||
};
|
};
|
||||||
// Write signed offset from table to its vtable.
|
// Write signed offset from table to its vtable.
|
||||||
let table_pos = self.owned_buf.len() - object_revloc_to_vtable.value() as usize;
|
let table_pos = self.owned_buf.len() - object_revloc_to_vtable.value() as usize;
|
||||||
let tmp_soffset_to_vt = unsafe { read_scalar_at::<UOffsetT>(&self.owned_buf, table_pos) };
|
if cfg!(debug_assertions) {
|
||||||
debug_assert_eq!(tmp_soffset_to_vt, 0xF0F0_F0F0);
|
// Safety:
|
||||||
|
// Verified slice length
|
||||||
|
let tmp_soffset_to_vt = unsafe {
|
||||||
|
read_scalar::<UOffsetT>(&self.owned_buf[table_pos..table_pos + SIZE_UOFFSET])
|
||||||
|
};
|
||||||
|
assert_eq!(tmp_soffset_to_vt, 0xF0F0_F0F0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let buf = &mut self.owned_buf[table_pos..table_pos + SIZE_SOFFSET];
|
||||||
|
// Safety:
|
||||||
|
// Verified length of buf above
|
||||||
unsafe {
|
unsafe {
|
||||||
emplace_scalar::<SOffsetT>(
|
emplace_scalar::<SOffsetT>(
|
||||||
&mut self.owned_buf[table_pos..table_pos + SIZE_SOFFSET],
|
buf,
|
||||||
final_vtable_revpos as SOffsetT - object_revloc_to_vtable.value() as SOffsetT
|
final_vtable_revpos as SOffsetT - object_revloc_to_vtable.value() as SOffsetT,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -623,7 +605,9 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
|
|||||||
}
|
}
|
||||||
// finally, zero out the old end data.
|
// finally, zero out the old end data.
|
||||||
{
|
{
|
||||||
let ptr = (&mut self.owned_buf[..middle]).as_mut_ptr();
|
let ptr = self.owned_buf[..middle].as_mut_ptr();
|
||||||
|
// Safety:
|
||||||
|
// ptr is byte aligned and of length middle
|
||||||
unsafe {
|
unsafe {
|
||||||
write_bytes(ptr, 0, middle);
|
write_bytes(ptr, 0, middle);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,24 @@
|
|||||||
|
|
||||||
use core::mem::size_of;
|
use core::mem::size_of;
|
||||||
|
|
||||||
|
mod private {
|
||||||
|
/// Types that are trivially transmutable are those where any combination of bits
|
||||||
|
/// represents a valid value of that type
|
||||||
|
///
|
||||||
|
/// For example integral types are TriviallyTransmutable as all bit patterns are valid,
|
||||||
|
/// however, `bool` is not trivially transmutable as only `0` and `1` are valid
|
||||||
|
pub trait TriviallyTransmutable {}
|
||||||
|
|
||||||
|
impl TriviallyTransmutable for i8 {}
|
||||||
|
impl TriviallyTransmutable for i16 {}
|
||||||
|
impl TriviallyTransmutable for i32 {}
|
||||||
|
impl TriviallyTransmutable for i64 {}
|
||||||
|
impl TriviallyTransmutable for u8 {}
|
||||||
|
impl TriviallyTransmutable for u16 {}
|
||||||
|
impl TriviallyTransmutable for u32 {}
|
||||||
|
impl TriviallyTransmutable for u64 {}
|
||||||
|
}
|
||||||
|
|
||||||
/// Trait for values that must be stored in little-endian byte order, but
|
/// Trait for values that must be stored in little-endian byte order, but
|
||||||
/// might be represented in memory as big-endian. Every type that implements
|
/// might be represented in memory as big-endian. Every type that implements
|
||||||
/// EndianScalar is a valid FlatBuffers scalar value.
|
/// EndianScalar is a valid FlatBuffers scalar value.
|
||||||
@@ -28,144 +46,118 @@ use core::mem::size_of;
|
|||||||
/// "too much". For example, num-traits provides i128 support, but that is an
|
/// "too much". For example, num-traits provides i128 support, but that is an
|
||||||
/// invalid FlatBuffers type.
|
/// invalid FlatBuffers type.
|
||||||
pub trait EndianScalar: Sized + PartialEq + Copy + Clone {
|
pub trait EndianScalar: Sized + PartialEq + Copy + Clone {
|
||||||
fn to_little_endian(self) -> Self;
|
type Scalar: private::TriviallyTransmutable;
|
||||||
fn from_little_endian(self) -> Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Macro for implementing a no-op endian conversion. This is used for types
|
fn to_little_endian(self) -> Self::Scalar;
|
||||||
/// that are one byte wide.
|
|
||||||
macro_rules! impl_endian_scalar_noop {
|
fn from_little_endian(v: Self::Scalar) -> Self;
|
||||||
($ty:ident) => {
|
|
||||||
impl EndianScalar for $ty {
|
|
||||||
#[inline]
|
|
||||||
fn to_little_endian(self) -> Self {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_little_endian(self) -> Self {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Macro for implementing an endian conversion using the stdlib `to_le` and
|
/// Macro for implementing an endian conversion using the stdlib `to_le` and
|
||||||
/// `from_le` functions. This is used for integer types. It is not used for
|
/// `from_le` functions. This is used for integer types. It is not used for
|
||||||
/// floats, because the `to_le` and `from_le` are not implemented for them in
|
/// floats, because the `to_le` and `from_le` are not implemented for them in
|
||||||
/// the stdlib.
|
/// the stdlib.
|
||||||
macro_rules! impl_endian_scalar_stdlib_le_conversion {
|
macro_rules! impl_endian_scalar {
|
||||||
($ty:ident) => {
|
($ty:ident) => {
|
||||||
impl EndianScalar for $ty {
|
impl EndianScalar for $ty {
|
||||||
|
type Scalar = Self;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_little_endian(self) -> Self {
|
fn to_little_endian(self) -> Self::Scalar {
|
||||||
Self::to_le(self)
|
Self::to_le(self)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_little_endian(self) -> Self {
|
fn from_little_endian(v: Self::Scalar) -> Self {
|
||||||
Self::from_le(self)
|
Self::from_le(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_endian_scalar_noop!(bool);
|
impl_endian_scalar!(u8);
|
||||||
impl_endian_scalar_noop!(u8);
|
impl_endian_scalar!(i8);
|
||||||
impl_endian_scalar_noop!(i8);
|
impl_endian_scalar!(u16);
|
||||||
|
impl_endian_scalar!(u32);
|
||||||
|
impl_endian_scalar!(u64);
|
||||||
|
impl_endian_scalar!(i16);
|
||||||
|
impl_endian_scalar!(i32);
|
||||||
|
impl_endian_scalar!(i64);
|
||||||
|
|
||||||
impl_endian_scalar_stdlib_le_conversion!(u16);
|
impl EndianScalar for bool {
|
||||||
impl_endian_scalar_stdlib_le_conversion!(u32);
|
type Scalar = u8;
|
||||||
impl_endian_scalar_stdlib_le_conversion!(u64);
|
|
||||||
impl_endian_scalar_stdlib_le_conversion!(i16);
|
fn to_little_endian(self) -> Self::Scalar {
|
||||||
impl_endian_scalar_stdlib_le_conversion!(i32);
|
self as u8
|
||||||
impl_endian_scalar_stdlib_le_conversion!(i64);
|
}
|
||||||
|
|
||||||
|
fn from_little_endian(v: Self::Scalar) -> Self {
|
||||||
|
v != 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl EndianScalar for f32 {
|
impl EndianScalar for f32 {
|
||||||
|
type Scalar = u32;
|
||||||
/// Convert f32 from host endian-ness to little-endian.
|
/// Convert f32 from host endian-ness to little-endian.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_little_endian(self) -> Self {
|
fn to_little_endian(self) -> u32 {
|
||||||
#[cfg(target_endian = "little")]
|
// Floats and Ints have the same endianness on all supported platforms.
|
||||||
{
|
// <https://doc.rust-lang.org/std/primitive.f32.html#method.from_bits>
|
||||||
self
|
self.to_bits().to_le()
|
||||||
}
|
|
||||||
#[cfg(not(target_endian = "little"))]
|
|
||||||
{
|
|
||||||
byte_swap_f32(self)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/// Convert f32 from little-endian to host endian-ness.
|
/// Convert f32 from little-endian to host endian-ness.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_little_endian(self) -> Self {
|
fn from_little_endian(v: u32) -> Self {
|
||||||
#[cfg(target_endian = "little")]
|
// Floats and Ints have the same endianness on all supported platforms.
|
||||||
{
|
// <https://doc.rust-lang.org/std/primitive.f32.html#method.from_bits>
|
||||||
self
|
f32::from_bits(u32::from_le(v))
|
||||||
}
|
|
||||||
#[cfg(not(target_endian = "little"))]
|
|
||||||
{
|
|
||||||
byte_swap_f32(self)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EndianScalar for f64 {
|
impl EndianScalar for f64 {
|
||||||
|
type Scalar = u64;
|
||||||
|
|
||||||
/// Convert f64 from host endian-ness to little-endian.
|
/// Convert f64 from host endian-ness to little-endian.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_little_endian(self) -> Self {
|
fn to_little_endian(self) -> u64 {
|
||||||
#[cfg(target_endian = "little")]
|
// Floats and Ints have the same endianness on all supported platforms.
|
||||||
{
|
// <https://doc.rust-lang.org/std/primitive.f64.html#method.from_bits>
|
||||||
self
|
self.to_bits().to_le()
|
||||||
}
|
|
||||||
#[cfg(not(target_endian = "little"))]
|
|
||||||
{
|
|
||||||
byte_swap_f64(self)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/// Convert f64 from little-endian to host endian-ness.
|
/// Convert f64 from little-endian to host endian-ness.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_little_endian(self) -> Self {
|
fn from_little_endian(v: u64) -> Self {
|
||||||
#[cfg(target_endian = "little")]
|
// Floats and Ints have the same endianness on all supported platforms.
|
||||||
{
|
// <https://doc.rust-lang.org/std/primitive.f64.html#method.from_bits>
|
||||||
self
|
f64::from_bits(u64::from_le(v))
|
||||||
}
|
|
||||||
#[cfg(not(target_endian = "little"))]
|
|
||||||
{
|
|
||||||
byte_swap_f64(self)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Swaps the bytes of an f32.
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[inline]
|
|
||||||
pub fn byte_swap_f32(x: f32) -> f32 {
|
|
||||||
f32::from_bits(x.to_bits().swap_bytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Swaps the bytes of an f64.
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[inline]
|
|
||||||
pub fn byte_swap_f64(x: f64) -> f64 {
|
|
||||||
f64::from_bits(x.to_bits().swap_bytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Place an EndianScalar into the provided mutable byte slice. Performs
|
/// Place an EndianScalar into the provided mutable byte slice. Performs
|
||||||
/// endian conversion, if necessary.
|
/// endian conversion, if necessary.
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// Caller must ensure `s.len() > size_of::<T>()`
|
/// Caller must ensure `s.len() >= size_of::<T>()`
|
||||||
/// and `x` does not overlap with `s`.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn emplace_scalar<T: EndianScalar>(s: &mut [u8], x: T) {
|
pub unsafe fn emplace_scalar<T: EndianScalar>(s: &mut [u8], x: T) {
|
||||||
|
let size = size_of::<T::Scalar>();
|
||||||
|
debug_assert!(
|
||||||
|
s.len() >= size,
|
||||||
|
"insufficient capacity for emplace_scalar, needed {} got {}",
|
||||||
|
size,
|
||||||
|
s.len()
|
||||||
|
);
|
||||||
|
|
||||||
let x_le = x.to_little_endian();
|
let x_le = x.to_little_endian();
|
||||||
core::ptr::copy_nonoverlapping(
|
core::ptr::copy_nonoverlapping(
|
||||||
&x_le as *const T as *const u8,
|
&x_le as *const T::Scalar as *const u8,
|
||||||
s.as_mut_ptr() as *mut u8,
|
s.as_mut_ptr() as *mut u8,
|
||||||
size_of::<T>(),
|
size,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read an EndianScalar from the provided byte slice at the specified location.
|
/// Read an EndianScalar from the provided byte slice at the specified location.
|
||||||
/// Performs endian conversion, if necessary.
|
/// Performs endian conversion, if necessary.
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// Caller must ensure `s.len() > loc + size_of::<T>()`.
|
/// Caller must ensure `s.len() >= loc + size_of::<T>()`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn read_scalar_at<T: EndianScalar>(s: &[u8], loc: usize) -> T {
|
pub unsafe fn read_scalar_at<T: EndianScalar>(s: &[u8], loc: usize) -> T {
|
||||||
read_scalar(&s[loc..])
|
read_scalar(&s[loc..])
|
||||||
@@ -177,8 +169,16 @@ pub unsafe fn read_scalar_at<T: EndianScalar>(s: &[u8], loc: usize) -> T {
|
|||||||
/// Caller must ensure `s.len() > size_of::<T>()`.
|
/// Caller must ensure `s.len() > size_of::<T>()`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn read_scalar<T: EndianScalar>(s: &[u8]) -> T {
|
pub unsafe fn read_scalar<T: EndianScalar>(s: &[u8]) -> T {
|
||||||
let mut mem = core::mem::MaybeUninit::<T>::uninit();
|
let size = size_of::<T::Scalar>();
|
||||||
|
debug_assert!(
|
||||||
|
s.len() >= size,
|
||||||
|
"insufficient capacity for emplace_scalar, needed {} got {}",
|
||||||
|
size,
|
||||||
|
s.len()
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut mem = core::mem::MaybeUninit::<T::Scalar>::uninit();
|
||||||
// Since [u8] has alignment 1, we copy it into T which may have higher alignment.
|
// Since [u8] has alignment 1, we copy it into T which may have higher alignment.
|
||||||
core::ptr::copy_nonoverlapping(s.as_ptr(), mem.as_mut_ptr() as *mut u8, size_of::<T>());
|
core::ptr::copy_nonoverlapping(s.as_ptr(), mem.as_mut_ptr() as *mut u8, size);
|
||||||
mem.assume_init().from_little_endian()
|
T::from_little_endian(mem.assume_init())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,11 @@ use core::marker::PhantomData;
|
|||||||
/// continue traversing the FlatBuffer.
|
/// continue traversing the FlatBuffer.
|
||||||
pub trait Follow<'buf> {
|
pub trait Follow<'buf> {
|
||||||
type Inner;
|
type Inner;
|
||||||
fn follow(buf: &'buf [u8], loc: usize) -> Self::Inner;
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// `buf[loc..]` must contain a valid value of `Self` and anything it
|
||||||
|
/// transitively refers to by offset must also be valid
|
||||||
|
unsafe fn follow(buf: &'buf [u8], loc: usize) -> Self::Inner;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// FollowStart wraps a Follow impl in a struct type. This can make certain
|
/// FollowStart wraps a Follow impl in a struct type. This can make certain
|
||||||
@@ -39,17 +43,21 @@ pub struct FollowStart<T>(PhantomData<T>);
|
|||||||
impl<'a, T: Follow<'a> + 'a> FollowStart<T> {
|
impl<'a, T: Follow<'a> + 'a> FollowStart<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self { 0: PhantomData }
|
Self(PhantomData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// `buf[loc..]` must contain a valid value of `T`
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn self_follow(&'a self, buf: &'a [u8], loc: usize) -> T::Inner {
|
pub unsafe fn self_follow(&'a self, buf: &'a [u8], loc: usize) -> T::Inner {
|
||||||
T::follow(buf, loc)
|
T::follow(buf, loc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a, T: Follow<'a>> Follow<'a> for FollowStart<T> {
|
impl<'a, T: Follow<'a>> Follow<'a> for FollowStart<T> {
|
||||||
type Inner = T::Inner;
|
type Inner = T::Inner;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||||
T::follow(buf, loc)
|
T::follow(buf, loc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ where
|
|||||||
{
|
{
|
||||||
let mut v = Verifier::new(opts, data);
|
let mut v = Verifier::new(opts, data);
|
||||||
<ForwardsUOffset<T>>::run_verifier(&mut v, 0)?;
|
<ForwardsUOffset<T>>::run_verifier(&mut v, 0)?;
|
||||||
|
// Safety:
|
||||||
|
// Run verifier above
|
||||||
Ok(unsafe { root_unchecked::<T>(data) })
|
Ok(unsafe { root_unchecked::<T>(data) })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,6 +77,8 @@ where
|
|||||||
{
|
{
|
||||||
let mut v = Verifier::new(opts, data);
|
let mut v = Verifier::new(opts, data);
|
||||||
<SkipSizePrefix<ForwardsUOffset<T>>>::run_verifier(&mut v, 0)?;
|
<SkipSizePrefix<ForwardsUOffset<T>>>::run_verifier(&mut v, 0)?;
|
||||||
|
// Safety:
|
||||||
|
// Run verifier above
|
||||||
Ok(unsafe { size_prefixed_root_unchecked::<T>(data) })
|
Ok(unsafe { size_prefixed_root_unchecked::<T>(data) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,9 +28,10 @@
|
|||||||
//! At this time, to generate Rust code, you will need the latest `master` version of `flatc`, available from here: <https://github.com/google/flatbuffers>
|
//! At this time, to generate Rust code, you will need the latest `master` version of `flatc`, available from here: <https://github.com/google/flatbuffers>
|
||||||
//! (On OSX, you can install FlatBuffers from `HEAD` with the Homebrew package manager.)
|
//! (On OSX, you can install FlatBuffers from `HEAD` with the Homebrew package manager.)
|
||||||
|
|
||||||
#![cfg_attr(feature = "no_std", no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
#![cfg_attr(all(nightly, not(feature = "std")), feature(error_in_core))]
|
||||||
|
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(not(feature = "std"))]
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
mod array;
|
mod array;
|
||||||
@@ -48,14 +49,12 @@ mod vtable_writer;
|
|||||||
|
|
||||||
pub use crate::array::{array_init, emplace_scalar_array, Array};
|
pub use crate::array::{array_init, emplace_scalar_array, Array};
|
||||||
pub use crate::builder::FlatBufferBuilder;
|
pub use crate::builder::FlatBufferBuilder;
|
||||||
pub use crate::endian_scalar::{
|
pub use crate::endian_scalar::{emplace_scalar, read_scalar, read_scalar_at, EndianScalar};
|
||||||
byte_swap_f32, byte_swap_f64, emplace_scalar, read_scalar, read_scalar_at, EndianScalar,
|
|
||||||
};
|
|
||||||
pub use crate::follow::{Follow, FollowStart};
|
pub use crate::follow::{Follow, FollowStart};
|
||||||
pub use crate::primitives::*;
|
pub use crate::primitives::*;
|
||||||
pub use crate::push::Push;
|
pub use crate::push::Push;
|
||||||
pub use crate::table::{buffer_has_identifier, Table};
|
pub use crate::table::{buffer_has_identifier, Table};
|
||||||
pub use crate::vector::{follow_cast_ref, SafeSliceAccess, Vector, VectorIter};
|
pub use crate::vector::{follow_cast_ref, Vector, VectorIter};
|
||||||
pub use crate::verifier::{
|
pub use crate::verifier::{
|
||||||
ErrorTraceDetail, InvalidFlatbuffer, SimpleToVerifyInSlice, Verifiable, Verifier,
|
ErrorTraceDetail, InvalidFlatbuffer, SimpleToVerifyInSlice, Verifiable, Verifier,
|
||||||
VerifierOptions,
|
VerifierOptions,
|
||||||
@@ -64,6 +63,4 @@ pub use crate::vtable::field_index_to_field_offset;
|
|||||||
pub use bitflags;
|
pub use bitflags;
|
||||||
pub use get_root::*;
|
pub use get_root::*;
|
||||||
|
|
||||||
// TODO(rw): Unify `create_vector` and `create_vector_direct` by using
|
|
||||||
// `Into<Vector<...>>`.
|
|
||||||
// TODO(rw): Split fill ops in builder into fill_small, fill_big like in C++.
|
// TODO(rw): Split fill ops in builder into fill_small, fill_big like in C++.
|
||||||
|
|||||||
@@ -112,10 +112,7 @@ impl<'a, T: 'a> WIPOffset<T> {
|
|||||||
/// Create a new WIPOffset.
|
/// Create a new WIPOffset.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(o: UOffsetT) -> WIPOffset<T> {
|
pub fn new(o: UOffsetT) -> WIPOffset<T> {
|
||||||
WIPOffset {
|
WIPOffset(o, PhantomData)
|
||||||
0: o,
|
|
||||||
1: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a wrapped value that brings its meaning as a union WIPOffset
|
/// Return a wrapped value that brings its meaning as a union WIPOffset
|
||||||
@@ -135,11 +132,9 @@ impl<T> Push for WIPOffset<T> {
|
|||||||
type Output = ForwardsUOffset<T>;
|
type Output = ForwardsUOffset<T>;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn push(&self, dst: &mut [u8], rest: &[u8]) {
|
unsafe fn push(&self, dst: &mut [u8], written_len: usize) {
|
||||||
let n = (SIZE_UOFFSET + rest.len() - self.value() as usize) as UOffsetT;
|
let n = (SIZE_UOFFSET + written_len - self.value() as usize) as UOffsetT;
|
||||||
unsafe {
|
emplace_scalar::<UOffsetT>(dst, n);
|
||||||
emplace_scalar::<UOffsetT>(dst, n);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,8 +142,8 @@ impl<T> Push for ForwardsUOffset<T> {
|
|||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn push(&self, dst: &mut [u8], rest: &[u8]) {
|
unsafe fn push(&self, dst: &mut [u8], written_len: usize) {
|
||||||
self.value().push(dst, rest);
|
self.value().push(dst, written_len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,9 +174,9 @@ impl<T> ForwardsUOffset<T> {
|
|||||||
impl<'a, T: Follow<'a>> Follow<'a> for ForwardsUOffset<T> {
|
impl<'a, T: Follow<'a>> Follow<'a> for ForwardsUOffset<T> {
|
||||||
type Inner = T::Inner;
|
type Inner = T::Inner;
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||||
let slice = &buf[loc..loc + SIZE_UOFFSET];
|
let slice = &buf[loc..loc + SIZE_UOFFSET];
|
||||||
let off = unsafe { read_scalar::<u32>(slice) as usize };
|
let off = read_scalar::<u32>(slice) as usize;
|
||||||
T::follow(buf, loc + off)
|
T::follow(buf, loc + off)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -200,9 +195,9 @@ impl<T> ForwardsVOffset<T> {
|
|||||||
impl<'a, T: Follow<'a>> Follow<'a> for ForwardsVOffset<T> {
|
impl<'a, T: Follow<'a>> Follow<'a> for ForwardsVOffset<T> {
|
||||||
type Inner = T::Inner;
|
type Inner = T::Inner;
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||||
let slice = &buf[loc..loc + SIZE_VOFFSET];
|
let slice = &buf[loc..loc + SIZE_VOFFSET];
|
||||||
let off = unsafe { read_scalar::<VOffsetT>(slice) as usize };
|
let off = read_scalar::<VOffsetT>(slice) as usize;
|
||||||
T::follow(buf, loc + off)
|
T::follow(buf, loc + off)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -211,8 +206,8 @@ impl<T> Push for ForwardsVOffset<T> {
|
|||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn push(&self, dst: &mut [u8], rest: &[u8]) {
|
unsafe fn push(&self, dst: &mut [u8], written_len: usize) {
|
||||||
self.value().push(dst, rest);
|
self.value().push(dst, written_len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,9 +225,9 @@ impl<T> BackwardsSOffset<T> {
|
|||||||
impl<'a, T: Follow<'a>> Follow<'a> for BackwardsSOffset<T> {
|
impl<'a, T: Follow<'a>> Follow<'a> for BackwardsSOffset<T> {
|
||||||
type Inner = T::Inner;
|
type Inner = T::Inner;
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||||
let slice = &buf[loc..loc + SIZE_SOFFSET];
|
let slice = &buf[loc..loc + SIZE_SOFFSET];
|
||||||
let off = unsafe { read_scalar::<SOffsetT>(slice) };
|
let off = read_scalar::<SOffsetT>(slice);
|
||||||
T::follow(buf, (loc as SOffsetT - off) as usize)
|
T::follow(buf, (loc as SOffsetT - off) as usize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -241,8 +236,8 @@ impl<T> Push for BackwardsSOffset<T> {
|
|||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn push(&self, dst: &mut [u8], rest: &[u8]) {
|
unsafe fn push(&self, dst: &mut [u8], written_len: usize) {
|
||||||
self.value().push(dst, rest);
|
self.value().push(dst, written_len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,7 +247,7 @@ pub struct SkipSizePrefix<T>(PhantomData<T>);
|
|||||||
impl<'a, T: Follow<'a> + 'a> Follow<'a> for SkipSizePrefix<T> {
|
impl<'a, T: Follow<'a> + 'a> Follow<'a> for SkipSizePrefix<T> {
|
||||||
type Inner = T::Inner;
|
type Inner = T::Inner;
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||||
T::follow(buf, loc + SIZE_SIZEPREFIX)
|
T::follow(buf, loc + SIZE_SIZEPREFIX)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -263,7 +258,7 @@ pub struct SkipRootOffset<T>(PhantomData<T>);
|
|||||||
impl<'a, T: Follow<'a> + 'a> Follow<'a> for SkipRootOffset<T> {
|
impl<'a, T: Follow<'a> + 'a> Follow<'a> for SkipRootOffset<T> {
|
||||||
type Inner = T::Inner;
|
type Inner = T::Inner;
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||||
T::follow(buf, loc + SIZE_UOFFSET)
|
T::follow(buf, loc + SIZE_UOFFSET)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -274,7 +269,7 @@ pub struct FileIdentifier;
|
|||||||
impl<'a> Follow<'a> for FileIdentifier {
|
impl<'a> Follow<'a> for FileIdentifier {
|
||||||
type Inner = &'a [u8];
|
type Inner = &'a [u8];
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||||
&buf[loc..loc + FILE_IDENTIFIER_LENGTH]
|
&buf[loc..loc + FILE_IDENTIFIER_LENGTH]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -286,7 +281,7 @@ pub struct SkipFileIdentifier<T>(PhantomData<T>);
|
|||||||
impl<'a, T: Follow<'a> + 'a> Follow<'a> for SkipFileIdentifier<T> {
|
impl<'a, T: Follow<'a> + 'a> Follow<'a> for SkipFileIdentifier<T> {
|
||||||
type Inner = T::Inner;
|
type Inner = T::Inner;
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||||
T::follow(buf, loc + FILE_IDENTIFIER_LENGTH)
|
T::follow(buf, loc + FILE_IDENTIFIER_LENGTH)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -294,8 +289,8 @@ impl<'a, T: Follow<'a> + 'a> Follow<'a> for SkipFileIdentifier<T> {
|
|||||||
impl<'a> Follow<'a> for bool {
|
impl<'a> Follow<'a> for bool {
|
||||||
type Inner = bool;
|
type Inner = bool;
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||||
unsafe { read_scalar_at::<u8>(buf, loc) != 0 }
|
read_scalar_at::<u8>(buf, loc) != 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,8 +304,8 @@ macro_rules! impl_follow_for_endian_scalar {
|
|||||||
impl<'a> Follow<'a> for $ty {
|
impl<'a> Follow<'a> for $ty {
|
||||||
type Inner = $ty;
|
type Inner = $ty;
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||||
unsafe { read_scalar_at::<$ty>(buf, loc) }
|
read_scalar_at::<$ty>(buf, loc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -24,7 +24,11 @@ use crate::endian_scalar::emplace_scalar;
|
|||||||
/// types.
|
/// types.
|
||||||
pub trait Push: Sized {
|
pub trait Push: Sized {
|
||||||
type Output;
|
type Output;
|
||||||
fn push(&self, dst: &mut [u8], _rest: &[u8]);
|
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// dst is aligned to [`Self::alignment`] and has length greater than or equal to [`Self::size`]
|
||||||
|
unsafe fn push(&self, dst: &mut [u8], written_len: usize);
|
||||||
#[inline]
|
#[inline]
|
||||||
fn size() -> usize {
|
fn size() -> usize {
|
||||||
size_of::<Self::Output>()
|
size_of::<Self::Output>()
|
||||||
@@ -35,13 +39,29 @@ pub trait Push: Sized {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, T: Push> Push for &'a T {
|
||||||
|
type Output = T::Output;
|
||||||
|
|
||||||
|
unsafe fn push(&self, dst: &mut [u8], written_len: usize) {
|
||||||
|
T::push(self, dst, written_len)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size() -> usize {
|
||||||
|
T::size()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn alignment() -> PushAlignment {
|
||||||
|
T::alignment()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Ensure Push alignment calculations are typesafe (because this helps reduce
|
/// Ensure Push alignment calculations are typesafe (because this helps reduce
|
||||||
/// implementation issues when using FlatBufferBuilder::align).
|
/// implementation issues when using FlatBufferBuilder::align).
|
||||||
pub struct PushAlignment(usize);
|
pub struct PushAlignment(usize);
|
||||||
impl PushAlignment {
|
impl PushAlignment {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(x: usize) -> Self {
|
pub fn new(x: usize) -> Self {
|
||||||
PushAlignment { 0: x }
|
PushAlignment(x)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn value(&self) -> usize {
|
pub fn value(&self) -> usize {
|
||||||
@@ -60,10 +80,8 @@ macro_rules! impl_push_for_endian_scalar {
|
|||||||
type Output = $ty;
|
type Output = $ty;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn push(&self, dst: &mut [u8], _rest: &[u8]) {
|
unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {
|
||||||
unsafe {
|
emplace_scalar::<$ty>(dst, *self);
|
||||||
emplace_scalar::<$ty>(dst, *self);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,23 +18,36 @@ use crate::follow::Follow;
|
|||||||
use crate::primitives::*;
|
use crate::primitives::*;
|
||||||
use crate::vtable::VTable;
|
use crate::vtable::VTable;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub struct Table<'a> {
|
pub struct Table<'a> {
|
||||||
pub buf: &'a [u8],
|
buf: &'a [u8],
|
||||||
pub loc: usize,
|
loc: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Table<'a> {
|
impl<'a> Table<'a> {
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// `buf` must contain a `soffset_t` at `loc`, which points to a valid vtable
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(buf: &'a [u8], loc: usize) -> Self {
|
pub unsafe fn new(buf: &'a [u8], loc: usize) -> Self {
|
||||||
Table { buf, loc }
|
Table { buf, loc }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn vtable(&self) -> VTable<'a> {
|
pub fn vtable(&self) -> VTable<'a> {
|
||||||
<BackwardsSOffset<VTable<'a>>>::follow(self.buf, self.loc)
|
// Safety:
|
||||||
|
// Table::new is created with a valid buf and location
|
||||||
|
unsafe { <BackwardsSOffset<VTable<'a>>>::follow(self.buf, self.loc) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieves the value at the provided `slot_byte_loc` returning `default`
|
||||||
|
/// if no value present
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// The value of the corresponding slot must have type T
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get<T: Follow<'a> + 'a>(
|
pub unsafe fn get<T: Follow<'a> + 'a>(
|
||||||
&self,
|
&self,
|
||||||
slot_byte_loc: VOffsetT,
|
slot_byte_loc: VOffsetT,
|
||||||
default: Option<T::Inner>,
|
default: Option<T::Inner>,
|
||||||
@@ -50,19 +63,26 @@ impl<'a> Table<'a> {
|
|||||||
impl<'a> Follow<'a> for Table<'a> {
|
impl<'a> Follow<'a> for Table<'a> {
|
||||||
type Inner = Table<'a>;
|
type Inner = Table<'a>;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||||
Table { buf, loc }
|
Table { buf, loc }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if data contains a prefix of `ident`
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn buffer_has_identifier(data: &[u8], ident: &str, size_prefixed: bool) -> bool {
|
pub fn buffer_has_identifier(data: &[u8], ident: &str, size_prefixed: bool) -> bool {
|
||||||
assert_eq!(ident.len(), FILE_IDENTIFIER_LENGTH);
|
assert_eq!(ident.len(), FILE_IDENTIFIER_LENGTH);
|
||||||
|
|
||||||
let got = if size_prefixed {
|
let got = if size_prefixed {
|
||||||
<SkipSizePrefix<SkipRootOffset<FileIdentifier>>>::follow(data, 0)
|
assert!(data.len() >= SIZE_SIZEPREFIX + SIZE_UOFFSET + FILE_IDENTIFIER_LENGTH);
|
||||||
|
// Safety:
|
||||||
|
// Verified data has sufficient bytes
|
||||||
|
unsafe { <SkipSizePrefix<SkipRootOffset<FileIdentifier>>>::follow(data, 0) }
|
||||||
} else {
|
} else {
|
||||||
<SkipRootOffset<FileIdentifier>>::follow(data, 0)
|
assert!(data.len() >= SIZE_UOFFSET + FILE_IDENTIFIER_LENGTH);
|
||||||
|
// Safety:
|
||||||
|
// Verified data has sufficient bytes
|
||||||
|
unsafe { <SkipRootOffset<FileIdentifier>>::follow(data, 0) }
|
||||||
};
|
};
|
||||||
|
|
||||||
ident.as_bytes() == got
|
ident.as_bytes() == got
|
||||||
|
|||||||
@@ -17,13 +17,10 @@
|
|||||||
use core::fmt::{Debug, Formatter, Result};
|
use core::fmt::{Debug, Formatter, Result};
|
||||||
use core::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator};
|
use core::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator};
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::mem::size_of;
|
use core::mem::{align_of, size_of};
|
||||||
use core::slice::from_raw_parts;
|
|
||||||
use core::str::from_utf8_unchecked;
|
use core::str::from_utf8_unchecked;
|
||||||
|
|
||||||
use crate::endian_scalar::read_scalar_at;
|
use crate::endian_scalar::read_scalar_at;
|
||||||
#[cfg(target_endian = "little")]
|
|
||||||
use crate::endian_scalar::EndianScalar;
|
|
||||||
use crate::follow::Follow;
|
use crate::follow::Follow;
|
||||||
use crate::primitives::*;
|
use crate::primitives::*;
|
||||||
|
|
||||||
@@ -55,6 +52,7 @@ where
|
|||||||
// and Clone for `T: Copy` and `T: Clone` respectively. However `Vector<'a, T>`
|
// and Clone for `T: Copy` and `T: Clone` respectively. However `Vector<'a, T>`
|
||||||
// can always be copied, no matter that `T` you have.
|
// can always be copied, no matter that `T` you have.
|
||||||
impl<'a, T> Copy for Vector<'a, T> {}
|
impl<'a, T> Copy for Vector<'a, T> {}
|
||||||
|
|
||||||
impl<'a, T> Clone for Vector<'a, T> {
|
impl<'a, T> Clone for Vector<'a, T> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
*self
|
*self
|
||||||
@@ -62,32 +60,46 @@ impl<'a, T> Clone for Vector<'a, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: 'a> Vector<'a, T> {
|
impl<'a, T: 'a> Vector<'a, T> {
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// `buf` contains a valid vector at `loc` consisting of
|
||||||
|
///
|
||||||
|
/// - UOffsetT element count
|
||||||
|
/// - Consecutive list of `T` elements
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn new(buf: &'a [u8], loc: usize) -> Self {
|
pub unsafe fn new(buf: &'a [u8], loc: usize) -> Self {
|
||||||
Vector {
|
Vector(buf, loc, PhantomData)
|
||||||
0: buf,
|
|
||||||
1: loc,
|
|
||||||
2: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
|
// Safety:
|
||||||
|
// Valid vector at time of construction starting with UOffsetT element count
|
||||||
unsafe { read_scalar_at::<UOffsetT>(self.0, self.1) as usize }
|
unsafe { read_scalar_at::<UOffsetT>(self.0, self.1) as usize }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.len() == 0
|
self.len() == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn bytes(&self) -> &'a [u8] {
|
||||||
|
let sz = size_of::<T>();
|
||||||
|
let len = self.len();
|
||||||
|
&self.0[self.1 + SIZE_UOFFSET..self.1 + SIZE_UOFFSET + sz * len]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Follow<'a> + 'a> Vector<'a, T> {
|
impl<'a, T: Follow<'a> + 'a> Vector<'a, T> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn get(&self, idx: usize) -> T::Inner {
|
pub fn get(&self, idx: usize) -> T::Inner {
|
||||||
assert!(idx < self.len() as usize);
|
assert!(idx < self.len());
|
||||||
let sz = size_of::<T>();
|
let sz = size_of::<T>();
|
||||||
debug_assert!(sz > 0);
|
debug_assert!(sz > 0);
|
||||||
T::follow(self.0, self.1 as usize + SIZE_UOFFSET + sz * idx)
|
// Safety:
|
||||||
|
// Valid vector at time of construction, verified that idx < element count
|
||||||
|
unsafe { T::follow(self.0, self.1 as usize + SIZE_UOFFSET + sz * idx) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -96,84 +108,40 @@ impl<'a, T: Follow<'a> + 'a> Vector<'a, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait SafeSliceAccess {}
|
/// # Safety
|
||||||
impl<'a, T: SafeSliceAccess + 'a> Vector<'a, T> {
|
///
|
||||||
pub fn safe_slice(self) -> &'a [T] {
|
/// `buf` must contain a value of T at `loc` and have alignment of 1
|
||||||
let buf = self.0;
|
pub unsafe fn follow_cast_ref<'a, T: Sized + 'a>(buf: &'a [u8], loc: usize) -> &'a T {
|
||||||
let loc = self.1;
|
assert_eq!(align_of::<T>(), 1);
|
||||||
let sz = size_of::<T>();
|
|
||||||
debug_assert!(sz > 0);
|
|
||||||
let len = unsafe { read_scalar_at::<UOffsetT>(buf, loc) } as usize;
|
|
||||||
let data_buf = &buf[loc + SIZE_UOFFSET..loc + SIZE_UOFFSET + len * sz];
|
|
||||||
let ptr = data_buf.as_ptr() as *const T;
|
|
||||||
let s: &'a [T] = unsafe { from_raw_parts(ptr, len) };
|
|
||||||
s
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SafeSliceAccess for u8 {}
|
|
||||||
impl SafeSliceAccess for i8 {}
|
|
||||||
impl SafeSliceAccess for bool {}
|
|
||||||
|
|
||||||
// TODO(caspern): Get rid of this. Conditional compliation is unnecessary complexity.
|
|
||||||
// Vectors of primitives just don't work on big endian machines!!!
|
|
||||||
#[cfg(target_endian = "little")]
|
|
||||||
mod le_safe_slice_impls {
|
|
||||||
impl super::SafeSliceAccess for u16 {}
|
|
||||||
impl super::SafeSliceAccess for u32 {}
|
|
||||||
impl super::SafeSliceAccess for u64 {}
|
|
||||||
|
|
||||||
impl super::SafeSliceAccess for i16 {}
|
|
||||||
impl super::SafeSliceAccess for i32 {}
|
|
||||||
impl super::SafeSliceAccess for i64 {}
|
|
||||||
|
|
||||||
impl super::SafeSliceAccess for f32 {}
|
|
||||||
impl super::SafeSliceAccess for f64 {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_endian = "little")]
|
|
||||||
pub use self::le_safe_slice_impls::*;
|
|
||||||
|
|
||||||
pub fn follow_cast_ref<'a, T: Sized + 'a>(buf: &'a [u8], loc: usize) -> &'a T {
|
|
||||||
let sz = size_of::<T>();
|
let sz = size_of::<T>();
|
||||||
let buf = &buf[loc..loc + sz];
|
let buf = &buf[loc..loc + sz];
|
||||||
let ptr = buf.as_ptr() as *const T;
|
let ptr = buf.as_ptr() as *const T;
|
||||||
unsafe { &*ptr }
|
// SAFETY
|
||||||
|
// buf contains a value at loc of type T and T has no alignment requirements
|
||||||
|
&*ptr
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Follow<'a> for &'a str {
|
impl<'a> Follow<'a> for &'a str {
|
||||||
type Inner = &'a str;
|
type Inner = &'a str;
|
||||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||||
let len = unsafe { read_scalar_at::<UOffsetT>(buf, loc) } as usize;
|
let len = read_scalar_at::<UOffsetT>(buf, loc) as usize;
|
||||||
let slice = &buf[loc + SIZE_UOFFSET..loc + SIZE_UOFFSET + len];
|
let slice = &buf[loc + SIZE_UOFFSET..loc + SIZE_UOFFSET + len];
|
||||||
unsafe { from_utf8_unchecked(slice) }
|
from_utf8_unchecked(slice)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_endian = "little")]
|
impl<'a> Follow<'a> for &'a [u8] {
|
||||||
fn follow_slice_helper<T>(buf: &[u8], loc: usize) -> &[T] {
|
type Inner = &'a [u8];
|
||||||
let sz = size_of::<T>();
|
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||||
debug_assert!(sz > 0);
|
let len = read_scalar_at::<UOffsetT>(buf, loc) as usize;
|
||||||
let len = unsafe { read_scalar_at::<UOffsetT>(buf, loc) as usize };
|
&buf[loc + SIZE_UOFFSET..loc + SIZE_UOFFSET + len]
|
||||||
let data_buf = &buf[loc + SIZE_UOFFSET..loc + SIZE_UOFFSET + len * sz];
|
|
||||||
let ptr = data_buf.as_ptr() as *const T;
|
|
||||||
let s: &[T] = unsafe { from_raw_parts(ptr, len) };
|
|
||||||
s
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Implement direct slice access if the host is little-endian.
|
|
||||||
#[cfg(target_endian = "little")]
|
|
||||||
impl<'a, T: EndianScalar> Follow<'a> for &'a [T] {
|
|
||||||
type Inner = &'a [T];
|
|
||||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
|
||||||
follow_slice_helper::<T>(buf, loc)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implement Follow for all possible Vectors that have Follow-able elements.
|
/// Implement Follow for all possible Vectors that have Follow-able elements.
|
||||||
impl<'a, T: Follow<'a> + 'a> Follow<'a> for Vector<'a, T> {
|
impl<'a, T: Follow<'a> + 'a> Follow<'a> for Vector<'a, T> {
|
||||||
type Inner = Vector<'a, T>;
|
type Inner = Vector<'a, T>;
|
||||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||||
Vector::new(buf, loc)
|
Vector::new(buf, loc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,8 +169,14 @@ impl<'a, T: 'a> VectorIter<'a, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new `VectorIter` from the provided slice
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// buf must contain a contiguous sequence of `items_num` values of `T`
|
||||||
|
///
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_slice(buf: &'a [u8], items_num: usize) -> Self {
|
pub unsafe fn from_slice(buf: &'a [u8], items_num: usize) -> Self {
|
||||||
VectorIter {
|
VectorIter {
|
||||||
buf,
|
buf,
|
||||||
loc: 0,
|
loc: 0,
|
||||||
@@ -235,7 +209,10 @@ impl<'a, T: Follow<'a> + 'a> Iterator for VectorIter<'a, T> {
|
|||||||
if self.remaining == 0 {
|
if self.remaining == 0 {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let result = T::follow(self.buf, self.loc);
|
// Safety:
|
||||||
|
// VectorIter can only be created from a contiguous sequence of `items_num`
|
||||||
|
// And remaining is initialized to `items_num`
|
||||||
|
let result = unsafe { T::follow(self.buf, self.loc) };
|
||||||
self.loc += sz;
|
self.loc += sz;
|
||||||
self.remaining -= 1;
|
self.remaining -= 1;
|
||||||
Some(result)
|
Some(result)
|
||||||
@@ -272,7 +249,10 @@ impl<'a, T: Follow<'a> + 'a> DoubleEndedIterator for VectorIter<'a, T> {
|
|||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
self.remaining -= 1;
|
self.remaining -= 1;
|
||||||
Some(T::follow(self.buf, self.loc + sz * self.remaining))
|
// Safety:
|
||||||
|
// VectorIter can only be created from a contiguous sequence of `items_num`
|
||||||
|
// And remaining is initialized to `items_num`
|
||||||
|
Some(unsafe { T::follow(self.buf, self.loc + sz * self.remaining) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,7 +289,7 @@ impl<'a, 'b, T: Follow<'a> + 'a> IntoIterator for &'b Vector<'a, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature="serialize")]
|
#[cfg(feature = "serialize")]
|
||||||
impl<'a, T> serde::ser::Serialize for Vector<'a, T>
|
impl<'a, T> serde::ser::Serialize for Vector<'a, T>
|
||||||
where
|
where
|
||||||
T: 'a + Follow<'a>,
|
T: 'a + Follow<'a>,
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
#[cfg(feature = "no_std")]
|
use crate::follow::Follow;
|
||||||
|
use crate::{ForwardsUOffset, SOffsetT, SkipSizePrefix, UOffsetT, VOffsetT, Vector, SIZE_UOFFSET};
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::ops::Range;
|
use core::ops::Range;
|
||||||
use core::option::Option;
|
use core::option::Option;
|
||||||
use crate::follow::Follow;
|
|
||||||
use crate::{ForwardsUOffset, SOffsetT, SkipSizePrefix, UOffsetT, VOffsetT, Vector, SIZE_UOFFSET};
|
|
||||||
|
|
||||||
#[cfg(feature="no_std")]
|
#[cfg(all(nightly, not(feature = "std")))]
|
||||||
use thiserror_core2::Error;
|
use core::error::Error;
|
||||||
#[cfg(not(feature="no_std"))]
|
#[cfg(feature = "std")]
|
||||||
use thiserror::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
/// Traces the location of data errors. Not populated for Dos detecting errors.
|
/// Traces the location of data errors. Not populated for Dos detecting errors.
|
||||||
/// Useful for MissingRequiredField and Utf8Error in particular, though
|
/// Useful for MissingRequiredField and Utf8Error in particular, though
|
||||||
@@ -28,8 +28,10 @@ pub enum ErrorTraceDetail {
|
|||||||
position: usize,
|
position: usize,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Default, Debug, Clone)]
|
#[derive(PartialEq, Eq, Default, Debug, Clone)]
|
||||||
pub struct ErrorTrace(Vec<ErrorTraceDetail>);
|
pub struct ErrorTrace(Vec<ErrorTraceDetail>);
|
||||||
|
|
||||||
impl core::convert::AsRef<[ErrorTraceDetail]> for ErrorTrace {
|
impl core::convert::AsRef<[ErrorTraceDetail]> for ErrorTrace {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn as_ref(&self) -> &[ErrorTraceDetail] {
|
fn as_ref(&self) -> &[ErrorTraceDetail] {
|
||||||
@@ -39,64 +41,138 @@ impl core::convert::AsRef<[ErrorTraceDetail]> for ErrorTrace {
|
|||||||
|
|
||||||
/// Describes how a flatuffer is invalid and, for data errors, roughly where. No extra tracing
|
/// Describes how a flatuffer is invalid and, for data errors, roughly where. No extra tracing
|
||||||
/// information is given for DoS detecting errors since it will probably be a lot.
|
/// information is given for DoS detecting errors since it will probably be a lot.
|
||||||
#[derive(Clone, Error, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum InvalidFlatbuffer {
|
pub enum InvalidFlatbuffer {
|
||||||
#[error("Missing required field `{required}`.\n{error_trace}")]
|
|
||||||
MissingRequiredField {
|
MissingRequiredField {
|
||||||
required: &'static str,
|
required: &'static str,
|
||||||
error_trace: ErrorTrace,
|
error_trace: ErrorTrace,
|
||||||
},
|
},
|
||||||
#[error(
|
|
||||||
"Union exactly one of union discriminant (`{field_type}`) and value \
|
|
||||||
(`{field}`) are present.\n{error_trace}"
|
|
||||||
)]
|
|
||||||
InconsistentUnion {
|
InconsistentUnion {
|
||||||
field: &'static str,
|
field: &'static str,
|
||||||
field_type: &'static str,
|
field_type: &'static str,
|
||||||
error_trace: ErrorTrace,
|
error_trace: ErrorTrace,
|
||||||
},
|
},
|
||||||
#[error("Utf8 error for string in {range:?}: {error}\n{error_trace}")]
|
|
||||||
Utf8Error {
|
Utf8Error {
|
||||||
#[source]
|
|
||||||
error: core::str::Utf8Error,
|
error: core::str::Utf8Error,
|
||||||
range: Range<usize>,
|
range: Range<usize>,
|
||||||
error_trace: ErrorTrace,
|
error_trace: ErrorTrace,
|
||||||
},
|
},
|
||||||
#[error("String in range [{}, {}) is missing its null terminator.\n{error_trace}",
|
|
||||||
range.start, range.end)]
|
|
||||||
MissingNullTerminator {
|
MissingNullTerminator {
|
||||||
range: Range<usize>,
|
range: Range<usize>,
|
||||||
error_trace: ErrorTrace,
|
error_trace: ErrorTrace,
|
||||||
},
|
},
|
||||||
#[error("Type `{unaligned_type}` at position {position} is unaligned.\n{error_trace}")]
|
|
||||||
Unaligned {
|
Unaligned {
|
||||||
position: usize,
|
position: usize,
|
||||||
unaligned_type: &'static str,
|
unaligned_type: &'static str,
|
||||||
error_trace: ErrorTrace,
|
error_trace: ErrorTrace,
|
||||||
},
|
},
|
||||||
#[error("Range [{}, {}) is out of bounds.\n{error_trace}", range.start, range.end)]
|
|
||||||
RangeOutOfBounds {
|
RangeOutOfBounds {
|
||||||
range: Range<usize>,
|
range: Range<usize>,
|
||||||
error_trace: ErrorTrace,
|
error_trace: ErrorTrace,
|
||||||
},
|
},
|
||||||
#[error(
|
|
||||||
"Signed offset at position {position} has value {soffset} which points out of bounds.\
|
|
||||||
\n{error_trace}"
|
|
||||||
)]
|
|
||||||
SignedOffsetOutOfBounds {
|
SignedOffsetOutOfBounds {
|
||||||
soffset: SOffsetT,
|
soffset: SOffsetT,
|
||||||
position: usize,
|
position: usize,
|
||||||
error_trace: ErrorTrace,
|
error_trace: ErrorTrace,
|
||||||
},
|
},
|
||||||
// Dos detecting errors. These do not get error traces since it will probably be very large.
|
// Dos detecting errors. These do not get error traces since it will probably be very large.
|
||||||
#[error("Too many tables.")]
|
|
||||||
TooManyTables,
|
TooManyTables,
|
||||||
#[error("Apparent size too large.")]
|
|
||||||
ApparentSizeTooLarge,
|
ApparentSizeTooLarge,
|
||||||
#[error("Nested table depth limit reached.")]
|
|
||||||
DepthLimitReached,
|
DepthLimitReached,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(nightly, feature = "std"))]
|
||||||
|
impl Error for InvalidFlatbuffer {
|
||||||
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
|
if let InvalidFlatbuffer::Utf8Error { error: source, .. } = self {
|
||||||
|
Some(source)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl core::fmt::Display for InvalidFlatbuffer {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||||
|
match self {
|
||||||
|
InvalidFlatbuffer::MissingRequiredField {
|
||||||
|
required,
|
||||||
|
error_trace,
|
||||||
|
} => {
|
||||||
|
writeln!(f, "Missing required field `{}`.\n{}", required, error_trace)?;
|
||||||
|
}
|
||||||
|
InvalidFlatbuffer::InconsistentUnion {
|
||||||
|
field,
|
||||||
|
field_type,
|
||||||
|
error_trace,
|
||||||
|
} => {
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
"Exactly one of union discriminant (`{}`) and value (`{}`) are present.\n{}",
|
||||||
|
field_type, field, error_trace
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
InvalidFlatbuffer::Utf8Error {
|
||||||
|
error,
|
||||||
|
range,
|
||||||
|
error_trace,
|
||||||
|
} => {
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
"Utf8 error for string in {:?}: {}\n{}",
|
||||||
|
range, error, error_trace
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
InvalidFlatbuffer::MissingNullTerminator { range, error_trace } => {
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
"String in range [{}, {}) is missing its null terminator.\n{}",
|
||||||
|
range.start, range.end, error_trace
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
InvalidFlatbuffer::Unaligned {
|
||||||
|
position,
|
||||||
|
unaligned_type,
|
||||||
|
error_trace,
|
||||||
|
} => {
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
"Type `{}` at position {} is unaligned.\n{}",
|
||||||
|
unaligned_type, position, error_trace
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
InvalidFlatbuffer::RangeOutOfBounds { range, error_trace } => {
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
"Range [{}, {}) is out of bounds.\n{}",
|
||||||
|
range.start, range.end, error_trace
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
InvalidFlatbuffer::SignedOffsetOutOfBounds {
|
||||||
|
soffset,
|
||||||
|
position,
|
||||||
|
error_trace,
|
||||||
|
} => {
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
"Signed offset at position {} has value {} which points out of bounds.\n{}",
|
||||||
|
position, soffset, error_trace
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
InvalidFlatbuffer::TooManyTables {} => {
|
||||||
|
writeln!(f, "Too many tables.")?;
|
||||||
|
}
|
||||||
|
InvalidFlatbuffer::ApparentSizeTooLarge {} => {
|
||||||
|
writeln!(f, "Apparent size too large.")?;
|
||||||
|
}
|
||||||
|
InvalidFlatbuffer::DepthLimitReached {} => {
|
||||||
|
writeln!(f, "Nested table depth limit reached.")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl core::fmt::Display for ErrorTrace {
|
impl core::fmt::Display for ErrorTrace {
|
||||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||||
use ErrorTraceDetail::*;
|
use ErrorTraceDetail::*;
|
||||||
@@ -184,6 +260,7 @@ fn trace_field<T>(res: Result<T>, field_name: &'static str, position: usize) ->
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a TableField trace detail if `res` is a data error.
|
/// Adds a TableField trace detail if `res` is a data error.
|
||||||
fn trace_elem<T>(res: Result<T>, index: usize, position: usize) -> Result<T> {
|
fn trace_elem<T>(res: Result<T>, index: usize, position: usize) -> Result<T> {
|
||||||
append_trace(res, ErrorTraceDetail::VectorElement { index, position })
|
append_trace(res, ErrorTraceDetail::VectorElement { index, position })
|
||||||
@@ -205,6 +282,7 @@ pub struct VerifierOptions {
|
|||||||
// options to error un-recognized enums and unions? possible footgun.
|
// options to error un-recognized enums and unions? possible footgun.
|
||||||
// Ignore nested flatbuffers, etc?
|
// Ignore nested flatbuffers, etc?
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for VerifierOptions {
|
impl Default for VerifierOptions {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -226,6 +304,7 @@ pub struct Verifier<'opts, 'buf> {
|
|||||||
num_tables: usize,
|
num_tables: usize,
|
||||||
apparent_size: usize,
|
apparent_size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'opts, 'buf> Verifier<'opts, 'buf> {
|
impl<'opts, 'buf> Verifier<'opts, 'buf> {
|
||||||
pub fn new(opts: &'opts VerifierOptions, buffer: &'buf [u8]) -> Self {
|
pub fn new(opts: &'opts VerifierOptions, buffer: &'buf [u8]) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -247,9 +326,12 @@ impl<'opts, 'buf> Verifier<'opts, 'buf> {
|
|||||||
/// memory since `buffer: &[u8]` has alignment 1.
|
/// memory since `buffer: &[u8]` has alignment 1.
|
||||||
///
|
///
|
||||||
/// ### WARNING
|
/// ### WARNING
|
||||||
|
///
|
||||||
/// This does not work for flatbuffers-structs as they have alignment 1 according to
|
/// This does not work for flatbuffers-structs as they have alignment 1 according to
|
||||||
/// `core::mem::align_of` but are meant to have higher alignment within a Flatbuffer w.r.t.
|
/// `core::mem::align_of` but are meant to have higher alignment within a Flatbuffer w.r.t.
|
||||||
/// `buffer[0]`. TODO(caspern).
|
/// `buffer[0]`. TODO(caspern).
|
||||||
|
///
|
||||||
|
/// Note this does not impact soundness as this crate does not assume alignment of structs
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_aligned<T>(&self, pos: usize) -> Result<()> {
|
fn is_aligned<T>(&self, pos: usize) -> Result<()> {
|
||||||
if pos % core::mem::align_of::<T>() == 0 {
|
if pos % core::mem::align_of::<T>() == 0 {
|
||||||
@@ -307,9 +389,9 @@ impl<'opts, 'buf> Verifier<'opts, 'buf> {
|
|||||||
|
|
||||||
// signed offsets are subtracted.
|
// signed offsets are subtracted.
|
||||||
let derefed = if offset > 0 {
|
let derefed = if offset > 0 {
|
||||||
pos.checked_sub(offset.abs() as usize)
|
pos.checked_sub(offset.unsigned_abs() as usize)
|
||||||
} else {
|
} else {
|
||||||
pos.checked_add(offset.abs() as usize)
|
pos.checked_add(offset.unsigned_abs() as usize)
|
||||||
};
|
};
|
||||||
if let Some(x) = derefed {
|
if let Some(x) = derefed {
|
||||||
if x < self.buffer.len() {
|
if x < self.buffer.len() {
|
||||||
@@ -372,6 +454,7 @@ pub struct TableVerifier<'ver, 'opts, 'buf> {
|
|||||||
// Verifier struct which holds the surrounding state and options.
|
// Verifier struct which holds the surrounding state and options.
|
||||||
verifier: &'ver mut Verifier<'opts, 'buf>,
|
verifier: &'ver mut Verifier<'opts, 'buf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ver, 'opts, 'buf> TableVerifier<'ver, 'opts, 'buf> {
|
impl<'ver, 'opts, 'buf> TableVerifier<'ver, 'opts, 'buf> {
|
||||||
fn deref(&mut self, field: VOffsetT) -> Result<Option<usize>> {
|
fn deref(&mut self, field: VOffsetT) -> Result<Option<usize>> {
|
||||||
let field = field as usize;
|
let field = field as usize;
|
||||||
@@ -439,7 +522,9 @@ impl<'ver, 'opts, 'buf> TableVerifier<'ver, 'opts, 'buf> {
|
|||||||
}
|
}
|
||||||
(Some(k), Some(v)) => {
|
(Some(k), Some(v)) => {
|
||||||
trace_field(Key::run_verifier(self.verifier, k), key_field_name, k)?;
|
trace_field(Key::run_verifier(self.verifier, k), key_field_name, k)?;
|
||||||
let discriminant = Key::follow(self.verifier.buffer, k);
|
// Safety:
|
||||||
|
// Run verifier on `k` above
|
||||||
|
let discriminant = unsafe { Key::follow(self.verifier.buffer, k) };
|
||||||
trace_field(
|
trace_field(
|
||||||
verify_union(discriminant, self.verifier, v),
|
verify_union(discriminant, self.verifier, v),
|
||||||
val_field_name,
|
val_field_name,
|
||||||
@@ -486,16 +571,27 @@ fn verify_vector_range<T>(v: &mut Verifier, pos: usize) -> Result<core::ops::Ran
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait SimpleToVerifyInSlice {}
|
pub trait SimpleToVerifyInSlice {}
|
||||||
|
|
||||||
impl SimpleToVerifyInSlice for bool {}
|
impl SimpleToVerifyInSlice for bool {}
|
||||||
|
|
||||||
impl SimpleToVerifyInSlice for i8 {}
|
impl SimpleToVerifyInSlice for i8 {}
|
||||||
|
|
||||||
impl SimpleToVerifyInSlice for u8 {}
|
impl SimpleToVerifyInSlice for u8 {}
|
||||||
|
|
||||||
impl SimpleToVerifyInSlice for i16 {}
|
impl SimpleToVerifyInSlice for i16 {}
|
||||||
|
|
||||||
impl SimpleToVerifyInSlice for u16 {}
|
impl SimpleToVerifyInSlice for u16 {}
|
||||||
|
|
||||||
impl SimpleToVerifyInSlice for i32 {}
|
impl SimpleToVerifyInSlice for i32 {}
|
||||||
|
|
||||||
impl SimpleToVerifyInSlice for u32 {}
|
impl SimpleToVerifyInSlice for u32 {}
|
||||||
|
|
||||||
impl SimpleToVerifyInSlice for f32 {}
|
impl SimpleToVerifyInSlice for f32 {}
|
||||||
|
|
||||||
impl SimpleToVerifyInSlice for i64 {}
|
impl SimpleToVerifyInSlice for i64 {}
|
||||||
|
|
||||||
impl SimpleToVerifyInSlice for u64 {}
|
impl SimpleToVerifyInSlice for u64 {}
|
||||||
|
|
||||||
impl SimpleToVerifyInSlice for f64 {}
|
impl SimpleToVerifyInSlice for f64 {}
|
||||||
|
|
||||||
impl<T: SimpleToVerifyInSlice> Verifiable for Vector<'_, T> {
|
impl<T: SimpleToVerifyInSlice> Verifiable for Vector<'_, T> {
|
||||||
|
|||||||
@@ -33,24 +33,42 @@ impl<'a> PartialEq for VTable<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> VTable<'a> {
|
impl<'a> VTable<'a> {
|
||||||
pub fn init(buf: &'a [u8], loc: usize) -> Self {
|
/// SAFETY
|
||||||
|
/// `buf` must contain a valid vtable at `loc`
|
||||||
|
///
|
||||||
|
/// This consists of a number of `VOffsetT`
|
||||||
|
/// - size of vtable in bytes including size element
|
||||||
|
/// - size of object in bytes including the vtable offset
|
||||||
|
/// - n fields where n is the number of fields in the table's schema when the code was compiled
|
||||||
|
pub unsafe fn init(buf: &'a [u8], loc: usize) -> Self {
|
||||||
VTable { buf, loc }
|
VTable { buf, loc }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn num_fields(&self) -> usize {
|
pub fn num_fields(&self) -> usize {
|
||||||
(self.num_bytes() / SIZE_VOFFSET) - 2
|
(self.num_bytes() / SIZE_VOFFSET) - 2
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn num_bytes(&self) -> usize {
|
pub fn num_bytes(&self) -> usize {
|
||||||
|
// Safety:
|
||||||
|
// Valid VTable at time of construction
|
||||||
unsafe { read_scalar_at::<VOffsetT>(self.buf, self.loc) as usize }
|
unsafe { read_scalar_at::<VOffsetT>(self.buf, self.loc) as usize }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn object_inline_num_bytes(&self) -> usize {
|
pub fn object_inline_num_bytes(&self) -> usize {
|
||||||
|
// Safety:
|
||||||
|
// Valid VTable at time of construction
|
||||||
let n = unsafe { read_scalar_at::<VOffsetT>(self.buf, self.loc + SIZE_VOFFSET) };
|
let n = unsafe { read_scalar_at::<VOffsetT>(self.buf, self.loc + SIZE_VOFFSET) };
|
||||||
n as usize
|
n as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_field(&self, idx: usize) -> VOffsetT {
|
pub fn get_field(&self, idx: usize) -> VOffsetT {
|
||||||
// TODO(rw): distinguish between None and 0?
|
// TODO(rw): distinguish between None and 0?
|
||||||
if idx > self.num_fields() {
|
if idx > self.num_fields() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Safety:
|
||||||
|
// Valid VTable at time of construction
|
||||||
unsafe {
|
unsafe {
|
||||||
read_scalar_at::<VOffsetT>(
|
read_scalar_at::<VOffsetT>(
|
||||||
self.buf,
|
self.buf,
|
||||||
@@ -58,13 +76,17 @@ impl<'a> VTable<'a> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, byte_loc: VOffsetT) -> VOffsetT {
|
pub fn get(&self, byte_loc: VOffsetT) -> VOffsetT {
|
||||||
// TODO(rw): distinguish between None and 0?
|
// TODO(rw): distinguish between None and 0?
|
||||||
if byte_loc as usize >= self.num_bytes() {
|
if byte_loc as usize + 2 > self.num_bytes() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
// Safety:
|
||||||
|
// byte_loc is within bounds of vtable, which was valid at time of construction
|
||||||
unsafe { read_scalar_at::<VOffsetT>(self.buf, self.loc + byte_loc as usize) }
|
unsafe { read_scalar_at::<VOffsetT>(self.buf, self.loc + byte_loc as usize) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_bytes(&self) -> &[u8] {
|
pub fn as_bytes(&self) -> &[u8] {
|
||||||
let len = self.num_bytes();
|
let len = self.num_bytes();
|
||||||
&self.buf[self.loc..self.loc + len]
|
&self.buf[self.loc..self.loc + len]
|
||||||
@@ -87,7 +109,7 @@ pub fn field_offset_to_field_index(field_o: VOffsetT) -> VOffsetT {
|
|||||||
|
|
||||||
impl<'a> Follow<'a> for VTable<'a> {
|
impl<'a> Follow<'a> for VTable<'a> {
|
||||||
type Inner = VTable<'a>;
|
type Inner = VTable<'a>;
|
||||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||||
VTable::init(buf, loc)
|
VTable::init(buf, loc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,8 +40,11 @@ impl<'a> VTableWriter<'a> {
|
|||||||
/// to the provided value.
|
/// to the provided value.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn write_vtable_byte_length(&mut self, n: VOffsetT) {
|
pub fn write_vtable_byte_length(&mut self, n: VOffsetT) {
|
||||||
|
let buf = &mut self.buf[..SIZE_VOFFSET];
|
||||||
|
// Safety:
|
||||||
|
// Validated range above
|
||||||
unsafe {
|
unsafe {
|
||||||
emplace_scalar::<VOffsetT>(&mut self.buf[..SIZE_VOFFSET], n);
|
emplace_scalar::<VOffsetT>(buf, n);
|
||||||
}
|
}
|
||||||
debug_assert_eq!(n as usize, self.buf.len());
|
debug_assert_eq!(n as usize, self.buf.len());
|
||||||
}
|
}
|
||||||
@@ -49,8 +52,11 @@ impl<'a> VTableWriter<'a> {
|
|||||||
/// Writes an object length (in bytes) into the vtable.
|
/// Writes an object length (in bytes) into the vtable.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn write_object_inline_size(&mut self, n: VOffsetT) {
|
pub fn write_object_inline_size(&mut self, n: VOffsetT) {
|
||||||
|
let buf = &mut self.buf[SIZE_VOFFSET..2 * SIZE_VOFFSET];
|
||||||
|
// Safety:
|
||||||
|
// Validated range above
|
||||||
unsafe {
|
unsafe {
|
||||||
emplace_scalar::<VOffsetT>(&mut self.buf[SIZE_VOFFSET..2 * SIZE_VOFFSET], n);
|
emplace_scalar::<VOffsetT>(buf, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,8 +67,11 @@ impl<'a> VTableWriter<'a> {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn write_field_offset(&mut self, vtable_offset: VOffsetT, object_data_offset: VOffsetT) {
|
pub fn write_field_offset(&mut self, vtable_offset: VOffsetT, object_data_offset: VOffsetT) {
|
||||||
let idx = vtable_offset as usize;
|
let idx = vtable_offset as usize;
|
||||||
|
let buf = &mut self.buf[idx..idx + SIZE_VOFFSET];
|
||||||
|
// Safety:
|
||||||
|
// Validated range above
|
||||||
unsafe {
|
unsafe {
|
||||||
emplace_scalar::<VOffsetT>(&mut self.buf[idx..idx + SIZE_VOFFSET], object_data_offset);
|
emplace_scalar::<VOffsetT>(buf, object_data_offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,6 +82,9 @@ impl<'a> VTableWriter<'a> {
|
|||||||
// This is the closest thing to memset in Rust right now.
|
// This is the closest thing to memset in Rust right now.
|
||||||
let len = self.buf.len();
|
let len = self.buf.len();
|
||||||
let p = self.buf.as_mut_ptr() as *mut u8;
|
let p = self.buf.as_mut_ptr() as *mut u8;
|
||||||
|
|
||||||
|
// Safety:
|
||||||
|
// p is byte aligned and of length `len`
|
||||||
unsafe {
|
unsafe {
|
||||||
write_bytes(p, 0, len);
|
write_bytes(p, 0, len);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ impl<'de> Buffer for &'de [u8] {
|
|||||||
/// Based off of the `empty` function, allows override for optimization purposes.
|
/// Based off of the `empty` function, allows override for optimization purposes.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn empty_str() -> Self::BufferString {
|
fn empty_str() -> Self::BufferString {
|
||||||
&""
|
""
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ impl<'a> MapBuilder<'a> {
|
|||||||
// Nested vector.
|
// Nested vector.
|
||||||
let start = Some(self.builder.values.len());
|
let start = Some(self.builder.values.len());
|
||||||
VectorBuilder {
|
VectorBuilder {
|
||||||
builder: &mut self.builder,
|
builder: self.builder,
|
||||||
start,
|
start,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@ impl<'a> MapBuilder<'a> {
|
|||||||
// Nested map.
|
// Nested map.
|
||||||
let start = Some(self.builder.values.len());
|
let start = Some(self.builder.values.len());
|
||||||
MapBuilder {
|
MapBuilder {
|
||||||
builder: &mut self.builder,
|
builder: self.builder,
|
||||||
start,
|
start,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ impl ser::Error for Error {
|
|||||||
Self::Serde(format!("{}", msg))
|
Self::Serde(format!("{}", msg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a> ser::SerializeSeq for &mut FlexbufferSerializer {
|
impl ser::SerializeSeq for &mut FlexbufferSerializer {
|
||||||
type Ok = ();
|
type Ok = ();
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||||
@@ -113,14 +113,14 @@ impl<'a> ser::SerializeSeq for &mut FlexbufferSerializer {
|
|||||||
}
|
}
|
||||||
// This is unlike a flexbuffers map which requires CString like keys.
|
// This is unlike a flexbuffers map which requires CString like keys.
|
||||||
// Its implemented as alternating keys and values (hopefully).
|
// Its implemented as alternating keys and values (hopefully).
|
||||||
impl<'a> ser::SerializeMap for &'a mut FlexbufferSerializer {
|
impl ser::SerializeMap for &mut FlexbufferSerializer {
|
||||||
type Ok = ();
|
type Ok = ();
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
|
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: Serialize,
|
||||||
{
|
{
|
||||||
key.serialize(MapKeySerializer(&mut **self))
|
key.serialize(MapKeySerializer(self))
|
||||||
}
|
}
|
||||||
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||||
where
|
where
|
||||||
@@ -132,7 +132,7 @@ impl<'a> ser::SerializeMap for &'a mut FlexbufferSerializer {
|
|||||||
self.end_map()
|
self.end_map()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a> ser::SerializeTuple for &mut FlexbufferSerializer {
|
impl ser::SerializeTuple for &mut FlexbufferSerializer {
|
||||||
type Ok = ();
|
type Ok = ();
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||||
@@ -145,7 +145,7 @@ impl<'a> ser::SerializeTuple for &mut FlexbufferSerializer {
|
|||||||
self.end_vector()
|
self.end_vector()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a> ser::SerializeTupleStruct for &mut FlexbufferSerializer {
|
impl ser::SerializeTupleStruct for &mut FlexbufferSerializer {
|
||||||
type Ok = ();
|
type Ok = ();
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||||
@@ -158,7 +158,7 @@ impl<'a> ser::SerializeTupleStruct for &mut FlexbufferSerializer {
|
|||||||
self.end_vector()
|
self.end_vector()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a> ser::SerializeStruct for &mut FlexbufferSerializer {
|
impl ser::SerializeStruct for &mut FlexbufferSerializer {
|
||||||
type Ok = ();
|
type Ok = ();
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
fn serialize_field<T: ?Sized>(
|
fn serialize_field<T: ?Sized>(
|
||||||
@@ -176,7 +176,7 @@ impl<'a> ser::SerializeStruct for &mut FlexbufferSerializer {
|
|||||||
self.end_map()
|
self.end_map()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a> ser::SerializeTupleVariant for &mut FlexbufferSerializer {
|
impl ser::SerializeTupleVariant for &mut FlexbufferSerializer {
|
||||||
type Ok = ();
|
type Ok = ();
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||||
@@ -190,7 +190,7 @@ impl<'a> ser::SerializeTupleVariant for &mut FlexbufferSerializer {
|
|||||||
self.end_map()
|
self.end_map()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a> ser::SerializeStructVariant for &mut FlexbufferSerializer {
|
impl ser::SerializeStructVariant for &mut FlexbufferSerializer {
|
||||||
type Ok = ();
|
type Ok = ();
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
fn serialize_field<T: ?Sized>(
|
fn serialize_field<T: ?Sized>(
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ impl<'a> VectorBuilder<'a> {
|
|||||||
pub fn start_vector(&mut self) -> VectorBuilder {
|
pub fn start_vector(&mut self) -> VectorBuilder {
|
||||||
let start = Some(self.builder.values.len());
|
let start = Some(self.builder.values.len());
|
||||||
VectorBuilder {
|
VectorBuilder {
|
||||||
builder: &mut self.builder,
|
builder: self.builder,
|
||||||
start,
|
start,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -48,7 +48,7 @@ impl<'a> VectorBuilder<'a> {
|
|||||||
pub fn start_map(&mut self) -> MapBuilder {
|
pub fn start_map(&mut self) -> MapBuilder {
|
||||||
let start = Some(self.builder.values.len());
|
let start = Some(self.builder.values.len());
|
||||||
MapBuilder {
|
MapBuilder {
|
||||||
builder: &mut self.builder,
|
builder: self.builder,
|
||||||
start,
|
start,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
// Serde with maps - field names and type names.
|
// Serde with maps - field names and type names.
|
||||||
|
|
||||||
// Until flat/flexbuffers is on Rust v1.42, we cannot use the previously unstable matches! macro.
|
// Until flat/flexbuffers is on Rust v1.42, we cannot use the previously unstable matches! macro.
|
||||||
#![allow(clippy::unknown_clippy_lints)]
|
#![allow(unknown_lints)]
|
||||||
#![allow(clippy::match_like_matches_macro)]
|
#![allow(clippy::match_like_matches_macro)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|||||||
@@ -380,7 +380,7 @@ impl<B: Buffer> Reader<B> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_blob(&self) -> Blob<B> {
|
pub fn as_blob(&self) -> Blob<B> {
|
||||||
self.get_blob().unwrap_or(Blob(B::empty()))
|
self.get_blob().unwrap_or_else(|_| Blob(B::empty()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves str pointer, errors if invalid UTF-8, or the provided index
|
/// Retrieves str pointer, errors if invalid UTF-8, or the provided index
|
||||||
@@ -580,8 +580,8 @@ impl<B: Buffer> Reader<B> {
|
|||||||
/// Returns empty string if you're not trying to read a string.
|
/// Returns empty string if you're not trying to read a string.
|
||||||
pub fn as_str(&self) -> B::BufferString {
|
pub fn as_str(&self) -> B::BufferString {
|
||||||
match self.fxb_type {
|
match self.fxb_type {
|
||||||
FlexBufferType::String => self.get_str().unwrap_or(B::empty_str()),
|
FlexBufferType::String => self.get_str().unwrap_or_else(|_| B::empty_str()),
|
||||||
FlexBufferType::Key => self.get_key().unwrap_or(B::empty_str()),
|
FlexBufferType::Key => self.get_key().unwrap_or_else(|_| B::empty_str()),
|
||||||
_ => B::empty_str(),
|
_ => B::empty_str(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@@ -9,8 +9,8 @@
|
|||||||
// Ensure the included flatbuffers.h is the same version as when this file was
|
// Ensure the included flatbuffers.h is the same version as when this file was
|
||||||
// generated, otherwise it may not be compatible.
|
// generated, otherwise it may not be compatible.
|
||||||
static_assert(FLATBUFFERS_VERSION_MAJOR == 22 &&
|
static_assert(FLATBUFFERS_VERSION_MAJOR == 22 &&
|
||||||
FLATBUFFERS_VERSION_MINOR == 9 &&
|
FLATBUFFERS_VERSION_MINOR == 10 &&
|
||||||
FLATBUFFERS_VERSION_REVISION == 24,
|
FLATBUFFERS_VERSION_REVISION == 25,
|
||||||
"Non-compatible flatbuffers version included");
|
"Non-compatible flatbuffers version included");
|
||||||
|
|
||||||
namespace MyGame {
|
namespace MyGame {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public enum MyGame_Sample_Equipment: UInt8, Enum {
|
|||||||
|
|
||||||
public struct MyGame_Sample_Vec3: NativeStruct {
|
public struct MyGame_Sample_Vec3: NativeStruct {
|
||||||
|
|
||||||
static func validateVersion() { FlatBuffersVersion_22_9_24() }
|
static func validateVersion() { FlatBuffersVersion_22_10_25() }
|
||||||
|
|
||||||
private var _x: Float32
|
private var _x: Float32
|
||||||
private var _y: Float32
|
private var _y: Float32
|
||||||
@@ -56,7 +56,7 @@ public struct MyGame_Sample_Vec3: NativeStruct {
|
|||||||
|
|
||||||
public struct MyGame_Sample_Vec3_Mutable: FlatBufferObject {
|
public struct MyGame_Sample_Vec3_Mutable: FlatBufferObject {
|
||||||
|
|
||||||
static func validateVersion() { FlatBuffersVersion_22_9_24() }
|
static func validateVersion() { FlatBuffersVersion_22_10_25() }
|
||||||
public var __buffer: ByteBuffer! { return _accessor.bb }
|
public var __buffer: ByteBuffer! { return _accessor.bb }
|
||||||
private var _accessor: Struct
|
private var _accessor: Struct
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ public struct MyGame_Sample_Vec3_Mutable: FlatBufferObject {
|
|||||||
|
|
||||||
public struct MyGame_Sample_Monster: FlatBufferObject {
|
public struct MyGame_Sample_Monster: FlatBufferObject {
|
||||||
|
|
||||||
static func validateVersion() { FlatBuffersVersion_22_9_24() }
|
static func validateVersion() { FlatBuffersVersion_22_10_25() }
|
||||||
public var __buffer: ByteBuffer! { return _accessor.bb }
|
public var __buffer: ByteBuffer! { return _accessor.bb }
|
||||||
private var _accessor: Table
|
private var _accessor: Table
|
||||||
|
|
||||||
@@ -162,7 +162,7 @@ public struct MyGame_Sample_Monster: FlatBufferObject {
|
|||||||
|
|
||||||
public struct MyGame_Sample_Weapon: FlatBufferObject {
|
public struct MyGame_Sample_Weapon: FlatBufferObject {
|
||||||
|
|
||||||
static func validateVersion() { FlatBuffersVersion_22_9_24() }
|
static func validateVersion() { FlatBuffersVersion_22_10_25() }
|
||||||
public var __buffer: ByteBuffer! { return _accessor.bb }
|
public var __buffer: ByteBuffer! { return _accessor.bb }
|
||||||
private var _accessor: Table
|
private var _accessor: Table
|
||||||
|
|
||||||
|
|||||||
@@ -59,10 +59,8 @@ impl core::fmt::Debug for Color {
|
|||||||
impl<'a> flatbuffers::Follow<'a> for Color {
|
impl<'a> flatbuffers::Follow<'a> for Color {
|
||||||
type Inner = Self;
|
type Inner = Self;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||||
let b = unsafe {
|
let b = flatbuffers::read_scalar_at::<i8>(buf, loc);
|
||||||
flatbuffers::read_scalar_at::<i8>(buf, loc)
|
|
||||||
};
|
|
||||||
Self(b)
|
Self(b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,21 +68,21 @@ impl<'a> flatbuffers::Follow<'a> for Color {
|
|||||||
impl flatbuffers::Push for Color {
|
impl flatbuffers::Push for Color {
|
||||||
type Output = Color;
|
type Output = Color;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn push(&self, dst: &mut [u8], _rest: &[u8]) {
|
unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {
|
||||||
unsafe { flatbuffers::emplace_scalar::<i8>(dst, self.0); }
|
flatbuffers::emplace_scalar::<i8>(dst, self.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl flatbuffers::EndianScalar for Color {
|
impl flatbuffers::EndianScalar for Color {
|
||||||
|
type Scalar = i8;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_little_endian(self) -> Self {
|
fn to_little_endian(self) -> i8 {
|
||||||
let b = i8::to_le(self.0);
|
self.0.to_le()
|
||||||
Self(b)
|
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(clippy::wrong_self_convention)]
|
#[allow(clippy::wrong_self_convention)]
|
||||||
fn from_little_endian(self) -> Self {
|
fn from_little_endian(v: i8) -> Self {
|
||||||
let b = i8::from_le(self.0);
|
let b = i8::from_le(v);
|
||||||
Self(b)
|
Self(b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,10 +55,8 @@ impl core::fmt::Debug for Equipment {
|
|||||||
impl<'a> flatbuffers::Follow<'a> for Equipment {
|
impl<'a> flatbuffers::Follow<'a> for Equipment {
|
||||||
type Inner = Self;
|
type Inner = Self;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||||
let b = unsafe {
|
let b = flatbuffers::read_scalar_at::<u8>(buf, loc);
|
||||||
flatbuffers::read_scalar_at::<u8>(buf, loc)
|
|
||||||
};
|
|
||||||
Self(b)
|
Self(b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,21 +64,21 @@ impl<'a> flatbuffers::Follow<'a> for Equipment {
|
|||||||
impl flatbuffers::Push for Equipment {
|
impl flatbuffers::Push for Equipment {
|
||||||
type Output = Equipment;
|
type Output = Equipment;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn push(&self, dst: &mut [u8], _rest: &[u8]) {
|
unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {
|
||||||
unsafe { flatbuffers::emplace_scalar::<u8>(dst, self.0); }
|
flatbuffers::emplace_scalar::<u8>(dst, self.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl flatbuffers::EndianScalar for Equipment {
|
impl flatbuffers::EndianScalar for Equipment {
|
||||||
|
type Scalar = u8;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_little_endian(self) -> Self {
|
fn to_little_endian(self) -> u8 {
|
||||||
let b = u8::to_le(self.0);
|
self.0.to_le()
|
||||||
Self(b)
|
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(clippy::wrong_self_convention)]
|
#[allow(clippy::wrong_self_convention)]
|
||||||
fn from_little_endian(self) -> Self {
|
fn from_little_endian(v: u8) -> Self {
|
||||||
let b = u8::from_le(self.0);
|
let b = u8::from_le(v);
|
||||||
Self(b)
|
Self(b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ pub struct Monster<'a> {
|
|||||||
impl<'a> flatbuffers::Follow<'a> for Monster<'a> {
|
impl<'a> flatbuffers::Follow<'a> for Monster<'a> {
|
||||||
type Inner = Monster<'a>;
|
type Inner = Monster<'a>;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||||
Self { _tab: flatbuffers::Table { buf, loc } }
|
Self { _tab: flatbuffers::Table::new(buf, loc) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ impl<'a> Monster<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
|
pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
|
||||||
Monster { _tab: table }
|
Monster { _tab: table }
|
||||||
}
|
}
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
@@ -73,7 +73,7 @@ impl<'a> Monster<'a> {
|
|||||||
x.to_string()
|
x.to_string()
|
||||||
});
|
});
|
||||||
let inventory = self.inventory().map(|x| {
|
let inventory = self.inventory().map(|x| {
|
||||||
x.to_vec()
|
x.into_iter().collect()
|
||||||
});
|
});
|
||||||
let color = self.color();
|
let color = self.color();
|
||||||
let weapons = self.weapons().map(|x| {
|
let weapons = self.weapons().map(|x| {
|
||||||
@@ -106,49 +106,84 @@ impl<'a> Monster<'a> {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn pos(&self) -> Option<&'a Vec3> {
|
pub fn pos(&self) -> Option<&'a Vec3> {
|
||||||
self._tab.get::<Vec3>(Monster::VT_POS, None)
|
// Safety:
|
||||||
|
// Created from valid Table for this object
|
||||||
|
// which contains a valid value in this slot
|
||||||
|
unsafe { self._tab.get::<Vec3>(Monster::VT_POS, None)}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn mana(&self) -> i16 {
|
pub fn mana(&self) -> i16 {
|
||||||
self._tab.get::<i16>(Monster::VT_MANA, Some(150)).unwrap()
|
// Safety:
|
||||||
|
// Created from valid Table for this object
|
||||||
|
// which contains a valid value in this slot
|
||||||
|
unsafe { self._tab.get::<i16>(Monster::VT_MANA, Some(150)).unwrap()}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn hp(&self) -> i16 {
|
pub fn hp(&self) -> i16 {
|
||||||
self._tab.get::<i16>(Monster::VT_HP, Some(100)).unwrap()
|
// Safety:
|
||||||
|
// Created from valid Table for this object
|
||||||
|
// which contains a valid value in this slot
|
||||||
|
unsafe { self._tab.get::<i16>(Monster::VT_HP, Some(100)).unwrap()}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn name(&self) -> Option<&'a str> {
|
pub fn name(&self) -> Option<&'a str> {
|
||||||
self._tab.get::<flatbuffers::ForwardsUOffset<&str>>(Monster::VT_NAME, None)
|
// Safety:
|
||||||
|
// Created from valid Table for this object
|
||||||
|
// which contains a valid value in this slot
|
||||||
|
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<&str>>(Monster::VT_NAME, None)}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn inventory(&self) -> Option<&'a [u8]> {
|
pub fn inventory(&self) -> Option<flatbuffers::Vector<'a, u8>> {
|
||||||
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, u8>>>(Monster::VT_INVENTORY, None).map(|v| v.safe_slice())
|
// Safety:
|
||||||
|
// Created from valid Table for this object
|
||||||
|
// which contains a valid value in this slot
|
||||||
|
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, u8>>>(Monster::VT_INVENTORY, None)}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn color(&self) -> Color {
|
pub fn color(&self) -> Color {
|
||||||
self._tab.get::<Color>(Monster::VT_COLOR, Some(Color::Blue)).unwrap()
|
// Safety:
|
||||||
|
// Created from valid Table for this object
|
||||||
|
// which contains a valid value in this slot
|
||||||
|
unsafe { self._tab.get::<Color>(Monster::VT_COLOR, Some(Color::Blue)).unwrap()}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn weapons(&self) -> Option<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<Weapon<'a>>>> {
|
pub fn weapons(&self) -> Option<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<Weapon<'a>>>> {
|
||||||
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<Weapon>>>>(Monster::VT_WEAPONS, None)
|
// Safety:
|
||||||
|
// Created from valid Table for this object
|
||||||
|
// which contains a valid value in this slot
|
||||||
|
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<Weapon>>>>(Monster::VT_WEAPONS, None)}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn equipped_type(&self) -> Equipment {
|
pub fn equipped_type(&self) -> Equipment {
|
||||||
self._tab.get::<Equipment>(Monster::VT_EQUIPPED_TYPE, Some(Equipment::NONE)).unwrap()
|
// Safety:
|
||||||
|
// Created from valid Table for this object
|
||||||
|
// which contains a valid value in this slot
|
||||||
|
unsafe { self._tab.get::<Equipment>(Monster::VT_EQUIPPED_TYPE, Some(Equipment::NONE)).unwrap()}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn equipped(&self) -> Option<flatbuffers::Table<'a>> {
|
pub fn equipped(&self) -> Option<flatbuffers::Table<'a>> {
|
||||||
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Table<'a>>>(Monster::VT_EQUIPPED, None)
|
// Safety:
|
||||||
|
// Created from valid Table for this object
|
||||||
|
// which contains a valid value in this slot
|
||||||
|
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Table<'a>>>(Monster::VT_EQUIPPED, None)}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn path(&self) -> Option<&'a [Vec3]> {
|
pub fn path(&self) -> Option<flatbuffers::Vector<'a, Vec3>> {
|
||||||
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, Vec3>>>(Monster::VT_PATH, None).map(|v| v.safe_slice())
|
// Safety:
|
||||||
|
// Created from valid Table for this object
|
||||||
|
// which contains a valid value in this slot
|
||||||
|
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, Vec3>>>(Monster::VT_PATH, None)}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn equipped_as_weapon(&self) -> Option<Weapon<'a>> {
|
pub fn equipped_as_weapon(&self) -> Option<Weapon<'a>> {
|
||||||
if self.equipped_type() == Equipment::Weapon {
|
if self.equipped_type() == Equipment::Weapon {
|
||||||
self.equipped().map(Weapon::init_from_table)
|
self.equipped().map(|t| {
|
||||||
|
// Safety:
|
||||||
|
// Created from a valid Table for this object
|
||||||
|
// Which contains a valid union in this slot
|
||||||
|
unsafe { Weapon::init_from_table(t) }
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@@ -365,18 +400,6 @@ impl MonsterT {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[inline]
|
|
||||||
#[deprecated(since="2.0.0", note="Deprecated in favor of `root_as...` methods.")]
|
|
||||||
pub fn get_root_as_monster<'a>(buf: &'a [u8]) -> Monster<'a> {
|
|
||||||
unsafe { flatbuffers::root_unchecked::<Monster<'a>>(buf) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
#[deprecated(since="2.0.0", note="Deprecated in favor of `root_as...` methods.")]
|
|
||||||
pub fn get_size_prefixed_root_as_monster<'a>(buf: &'a [u8]) -> Monster<'a> {
|
|
||||||
unsafe { flatbuffers::size_prefixed_root_unchecked::<Monster<'a>>(buf) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Verifies that a buffer of bytes contains a `Monster`
|
/// Verifies that a buffer of bytes contains a `Monster`
|
||||||
/// and returns it.
|
/// and returns it.
|
||||||
|
|||||||
@@ -29,39 +29,25 @@ impl core::fmt::Debug for Vec3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl flatbuffers::SimpleToVerifyInSlice for Vec3 {}
|
impl flatbuffers::SimpleToVerifyInSlice for Vec3 {}
|
||||||
impl flatbuffers::SafeSliceAccess for Vec3 {}
|
|
||||||
impl<'a> flatbuffers::Follow<'a> for Vec3 {
|
impl<'a> flatbuffers::Follow<'a> for Vec3 {
|
||||||
type Inner = &'a Vec3;
|
type Inner = &'a Vec3;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||||
<&'a Vec3>::follow(buf, loc)
|
<&'a Vec3>::follow(buf, loc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a> flatbuffers::Follow<'a> for &'a Vec3 {
|
impl<'a> flatbuffers::Follow<'a> for &'a Vec3 {
|
||||||
type Inner = &'a Vec3;
|
type Inner = &'a Vec3;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||||
flatbuffers::follow_cast_ref::<Vec3>(buf, loc)
|
flatbuffers::follow_cast_ref::<Vec3>(buf, loc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'b> flatbuffers::Push for Vec3 {
|
impl<'b> flatbuffers::Push for Vec3 {
|
||||||
type Output = Vec3;
|
type Output = Vec3;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn push(&self, dst: &mut [u8], _rest: &[u8]) {
|
unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {
|
||||||
let src = unsafe {
|
let src = ::core::slice::from_raw_parts(self as *const Vec3 as *const u8, Self::size());
|
||||||
::core::slice::from_raw_parts(self as *const Vec3 as *const u8, Self::size())
|
|
||||||
};
|
|
||||||
dst.copy_from_slice(src);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'b> flatbuffers::Push for &'b Vec3 {
|
|
||||||
type Output = Vec3;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn push(&self, dst: &mut [u8], _rest: &[u8]) {
|
|
||||||
let src = unsafe {
|
|
||||||
::core::slice::from_raw_parts(*self as *const Vec3 as *const u8, Self::size())
|
|
||||||
};
|
|
||||||
dst.copy_from_slice(src);
|
dst.copy_from_slice(src);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,70 +81,88 @@ impl<'a> Vec3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn x(&self) -> f32 {
|
pub fn x(&self) -> f32 {
|
||||||
let mut mem = core::mem::MaybeUninit::<f32>::uninit();
|
let mut mem = core::mem::MaybeUninit::<<f32 as EndianScalar>::Scalar>::uninit();
|
||||||
unsafe {
|
// Safety:
|
||||||
|
// Created from a valid Table for this object
|
||||||
|
// Which contains a valid value in this slot
|
||||||
|
EndianScalar::from_little_endian(unsafe {
|
||||||
core::ptr::copy_nonoverlapping(
|
core::ptr::copy_nonoverlapping(
|
||||||
self.0[0..].as_ptr(),
|
self.0[0..].as_ptr(),
|
||||||
mem.as_mut_ptr() as *mut u8,
|
mem.as_mut_ptr() as *mut u8,
|
||||||
core::mem::size_of::<f32>(),
|
core::mem::size_of::<<f32 as EndianScalar>::Scalar>(),
|
||||||
);
|
);
|
||||||
mem.assume_init()
|
mem.assume_init()
|
||||||
}.from_little_endian()
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_x(&mut self, x: f32) {
|
pub fn set_x(&mut self, x: f32) {
|
||||||
let x_le = x.to_little_endian();
|
let x_le = x.to_little_endian();
|
||||||
|
// Safety:
|
||||||
|
// Created from a valid Table for this object
|
||||||
|
// Which contains a valid value in this slot
|
||||||
unsafe {
|
unsafe {
|
||||||
core::ptr::copy_nonoverlapping(
|
core::ptr::copy_nonoverlapping(
|
||||||
&x_le as *const f32 as *const u8,
|
&x_le as *const _ as *const u8,
|
||||||
self.0[0..].as_mut_ptr(),
|
self.0[0..].as_mut_ptr(),
|
||||||
core::mem::size_of::<f32>(),
|
core::mem::size_of::<<f32 as EndianScalar>::Scalar>(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn y(&self) -> f32 {
|
pub fn y(&self) -> f32 {
|
||||||
let mut mem = core::mem::MaybeUninit::<f32>::uninit();
|
let mut mem = core::mem::MaybeUninit::<<f32 as EndianScalar>::Scalar>::uninit();
|
||||||
unsafe {
|
// Safety:
|
||||||
|
// Created from a valid Table for this object
|
||||||
|
// Which contains a valid value in this slot
|
||||||
|
EndianScalar::from_little_endian(unsafe {
|
||||||
core::ptr::copy_nonoverlapping(
|
core::ptr::copy_nonoverlapping(
|
||||||
self.0[4..].as_ptr(),
|
self.0[4..].as_ptr(),
|
||||||
mem.as_mut_ptr() as *mut u8,
|
mem.as_mut_ptr() as *mut u8,
|
||||||
core::mem::size_of::<f32>(),
|
core::mem::size_of::<<f32 as EndianScalar>::Scalar>(),
|
||||||
);
|
);
|
||||||
mem.assume_init()
|
mem.assume_init()
|
||||||
}.from_little_endian()
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_y(&mut self, x: f32) {
|
pub fn set_y(&mut self, x: f32) {
|
||||||
let x_le = x.to_little_endian();
|
let x_le = x.to_little_endian();
|
||||||
|
// Safety:
|
||||||
|
// Created from a valid Table for this object
|
||||||
|
// Which contains a valid value in this slot
|
||||||
unsafe {
|
unsafe {
|
||||||
core::ptr::copy_nonoverlapping(
|
core::ptr::copy_nonoverlapping(
|
||||||
&x_le as *const f32 as *const u8,
|
&x_le as *const _ as *const u8,
|
||||||
self.0[4..].as_mut_ptr(),
|
self.0[4..].as_mut_ptr(),
|
||||||
core::mem::size_of::<f32>(),
|
core::mem::size_of::<<f32 as EndianScalar>::Scalar>(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn z(&self) -> f32 {
|
pub fn z(&self) -> f32 {
|
||||||
let mut mem = core::mem::MaybeUninit::<f32>::uninit();
|
let mut mem = core::mem::MaybeUninit::<<f32 as EndianScalar>::Scalar>::uninit();
|
||||||
unsafe {
|
// Safety:
|
||||||
|
// Created from a valid Table for this object
|
||||||
|
// Which contains a valid value in this slot
|
||||||
|
EndianScalar::from_little_endian(unsafe {
|
||||||
core::ptr::copy_nonoverlapping(
|
core::ptr::copy_nonoverlapping(
|
||||||
self.0[8..].as_ptr(),
|
self.0[8..].as_ptr(),
|
||||||
mem.as_mut_ptr() as *mut u8,
|
mem.as_mut_ptr() as *mut u8,
|
||||||
core::mem::size_of::<f32>(),
|
core::mem::size_of::<<f32 as EndianScalar>::Scalar>(),
|
||||||
);
|
);
|
||||||
mem.assume_init()
|
mem.assume_init()
|
||||||
}.from_little_endian()
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_z(&mut self, x: f32) {
|
pub fn set_z(&mut self, x: f32) {
|
||||||
let x_le = x.to_little_endian();
|
let x_le = x.to_little_endian();
|
||||||
|
// Safety:
|
||||||
|
// Created from a valid Table for this object
|
||||||
|
// Which contains a valid value in this slot
|
||||||
unsafe {
|
unsafe {
|
||||||
core::ptr::copy_nonoverlapping(
|
core::ptr::copy_nonoverlapping(
|
||||||
&x_le as *const f32 as *const u8,
|
&x_le as *const _ as *const u8,
|
||||||
self.0[8..].as_mut_ptr(),
|
self.0[8..].as_mut_ptr(),
|
||||||
core::mem::size_of::<f32>(),
|
core::mem::size_of::<<f32 as EndianScalar>::Scalar>(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ pub struct Weapon<'a> {
|
|||||||
impl<'a> flatbuffers::Follow<'a> for Weapon<'a> {
|
impl<'a> flatbuffers::Follow<'a> for Weapon<'a> {
|
||||||
type Inner = Weapon<'a>;
|
type Inner = Weapon<'a>;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||||
Self { _tab: flatbuffers::Table { buf, loc } }
|
Self { _tab: flatbuffers::Table::new(buf, loc) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ impl<'a> Weapon<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
|
pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
|
||||||
Weapon { _tab: table }
|
Weapon { _tab: table }
|
||||||
}
|
}
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
@@ -60,11 +60,17 @@ impl<'a> Weapon<'a> {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn name(&self) -> Option<&'a str> {
|
pub fn name(&self) -> Option<&'a str> {
|
||||||
self._tab.get::<flatbuffers::ForwardsUOffset<&str>>(Weapon::VT_NAME, None)
|
// Safety:
|
||||||
|
// Created from valid Table for this object
|
||||||
|
// which contains a valid value in this slot
|
||||||
|
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<&str>>(Weapon::VT_NAME, None)}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn damage(&self) -> i16 {
|
pub fn damage(&self) -> i16 {
|
||||||
self._tab.get::<i16>(Weapon::VT_DAMAGE, Some(0)).unwrap()
|
// Safety:
|
||||||
|
// Created from valid Table for this object
|
||||||
|
// which contains a valid value in this slot
|
||||||
|
unsafe { self._tab.get::<i16>(Weapon::VT_DAMAGE, Some(0)).unwrap()}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ extern crate flatbuffers;
|
|||||||
|
|
||||||
// import the generated code
|
// import the generated code
|
||||||
#[allow(dead_code, unused_imports)]
|
#[allow(dead_code, unused_imports)]
|
||||||
#[allow(clippy::approx_constant)] // We use low precision PI as a default value.
|
#[allow(clippy::all)]
|
||||||
mod rust_generated;
|
mod rust_generated;
|
||||||
pub use rust_generated::my_game::sample::{Color, Equipment,
|
pub use rust_generated::my_game::sample::{Color, Equipment,
|
||||||
Monster, MonsterArgs,
|
Monster, MonsterArgs,
|
||||||
@@ -122,10 +122,7 @@ fn main() {
|
|||||||
// Get an element from the `inventory` FlatBuffer's `vector`.
|
// Get an element from the `inventory` FlatBuffer's `vector`.
|
||||||
assert!(monster.inventory().is_some());
|
assert!(monster.inventory().is_some());
|
||||||
let inv = monster.inventory().unwrap();
|
let inv = monster.inventory().unwrap();
|
||||||
|
let third_item = inv.get(2);
|
||||||
// Note that this vector is returned as a slice, because direct access for
|
|
||||||
// this type, a u8 vector, is safe on all platforms:
|
|
||||||
let third_item = inv[2];
|
|
||||||
assert_eq!(third_item, 2);
|
assert_eq!(third_item, 2);
|
||||||
|
|
||||||
// Get and test the `weapons` FlatBuffers's `vector`.
|
// Get and test the `weapons` FlatBuffers's `vector`.
|
||||||
|
|||||||
@@ -449,6 +449,13 @@ flatc(
|
|||||||
cwd=swift_code_gen
|
cwd=swift_code_gen
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Nim Tests
|
||||||
|
NIM_OPTS = BASE_OPTS + ["--nim"]
|
||||||
|
flatc(NIM_OPTS, schema="monster_test.fbs", include="include_test")
|
||||||
|
flatc(NIM_OPTS, schema="optional_scalars.fbs")
|
||||||
|
flatc(NIM_OPTS, schema="more_defaults.fbs")
|
||||||
|
flatc(NIM_OPTS, schema="MutatingBool.fbs")
|
||||||
|
|
||||||
# --filename-suffix and --filename-ext tests
|
# --filename-suffix and --filename-ext tests
|
||||||
flatc(
|
flatc(
|
||||||
CPP_OPTS + NO_INCL_OPTS + ["--grpc", "--filename-ext", "hpp"],
|
CPP_OPTS + NO_INCL_OPTS + ["--grpc", "--filename-ext", "hpp"],
|
||||||
|
|||||||
76
scripts/release.sh
Executable file
76
scripts/release.sh
Executable file
@@ -0,0 +1,76 @@
|
|||||||
|
|
||||||
|
printf -v year '%(%y)T' -1
|
||||||
|
printf -v month '%(%m)T' -1
|
||||||
|
printf -v day '%(%d)T' -1
|
||||||
|
|
||||||
|
version="$year.$month.$day"
|
||||||
|
version_underscore="$year\_$month\_$day"
|
||||||
|
|
||||||
|
echo "Setting Flatbuffers Version to: $version"
|
||||||
|
|
||||||
|
echo "Updating include/flatbuffers/base.h..."
|
||||||
|
sed -i \
|
||||||
|
-e "s/\(#define FLATBUFFERS_VERSION_MAJOR \).*/\1$year/" \
|
||||||
|
-e "s/\(#define FLATBUFFERS_VERSION_MINOR \).*/\1$month/" \
|
||||||
|
-e "s/\(#define FLATBUFFERS_VERSION_REVISION \).*/\1$day/" \
|
||||||
|
include/flatbuffers/base.h
|
||||||
|
|
||||||
|
echo "Updating CMake\Version.cmake..."
|
||||||
|
sed -i \
|
||||||
|
-e "s/\(set(VERSION_MAJOR \).*/\1$year)/" \
|
||||||
|
-e "s/\(set(VERSION_MINOR \).*/\1$month)/" \
|
||||||
|
-e "s/\(set(VERSION_PATCH \).*/\1$day)/" \
|
||||||
|
CMake/Version.cmake
|
||||||
|
|
||||||
|
echo "Updating include/flatbuffers/reflection_generated.h..."
|
||||||
|
echo "Updating tests/evolution_test/evolution_v1_generated.h..."
|
||||||
|
echo "Updating tests/evolution_test/evolution_v1_generated.h..."
|
||||||
|
sed -i \
|
||||||
|
-e "s/\(FLATBUFFERS_VERSION_MAJOR == \)[0-9]*\(.*\)/\1$year\2/" \
|
||||||
|
-e "s/\(FLATBUFFERS_VERSION_MINOR == \)[0-9]*\(.*\)/\1$month\2/" \
|
||||||
|
-e "s/\(FLATBUFFERS_VERSION_REVISION == \)[0-9]*\(.*\)/\1$day\2/" \
|
||||||
|
include/flatbuffers/reflection_generated.h \
|
||||||
|
tests/evolution_test/evolution_v1_generated.h \
|
||||||
|
tests/evolution_test/evolution_v2_generated.h
|
||||||
|
|
||||||
|
echo "Updating java/pom.xml..."
|
||||||
|
xmlstarlet edit --inplace -N s=http://maven.apache.org/POM/4.0.0 \
|
||||||
|
--update '//s:project/s:version' --value $version \
|
||||||
|
java/pom.xml
|
||||||
|
|
||||||
|
echo "Updating package.json..."
|
||||||
|
sed -i \
|
||||||
|
-e "s/\(\"version\": \).*/\1\"$version\",/" \
|
||||||
|
package.json
|
||||||
|
|
||||||
|
echo "Updating net/FlatBuffers/Google.FlatBuffers.csproj..."
|
||||||
|
sed -i \
|
||||||
|
-e "s/\(<PackageVersion>\).*\(<\/PackageVersion>\)/\1$version\2/" \
|
||||||
|
net/FlatBuffers/Google.FlatBuffers.csproj
|
||||||
|
|
||||||
|
echo "Updating dart/pubspec.yaml..."
|
||||||
|
sed -i \
|
||||||
|
-e "s/\(version: \).*/\1$version/" \
|
||||||
|
dart/pubspec.yaml
|
||||||
|
|
||||||
|
echo "Updating python/flatbuffers/_version.py..."
|
||||||
|
sed -i \
|
||||||
|
-e "s/\(__version__ = u\).*/\1\"$version\"/" \
|
||||||
|
python/flatbuffers/_version.py
|
||||||
|
|
||||||
|
echo "Updating FlatBuffers.podspec..."
|
||||||
|
sed -i \
|
||||||
|
-e "s/\(s.version\s*= \).*/\1'$version'/" \
|
||||||
|
FlatBuffers.podspec
|
||||||
|
|
||||||
|
echo "Updating FlatBuffersVersion_X_X_X() version check...."
|
||||||
|
grep -rl 'FlatBuffersVersion_' * --exclude=release.sh | xargs -i@ \
|
||||||
|
sed -i \
|
||||||
|
-e "s/\(FlatBuffersVersion_\).*()/\1$version_underscore()/g" \
|
||||||
|
@
|
||||||
|
|
||||||
|
echo "Updating FLATBUFFERS_X_X_X() version check...."
|
||||||
|
grep -rl 'FLATBUFFERS_\d*' * --exclude=release.sh | xargs -i@ \
|
||||||
|
sed -i \
|
||||||
|
-e "s/\(FLATBUFFERS_\)[0-9]\{2\}.*()/\1$version_underscore()/g" \
|
||||||
|
@
|
||||||
@@ -39,6 +39,8 @@ cc_library(
|
|||||||
"bfbs_gen.h",
|
"bfbs_gen.h",
|
||||||
"bfbs_gen_lua.cpp",
|
"bfbs_gen_lua.cpp",
|
||||||
"bfbs_gen_lua.h",
|
"bfbs_gen_lua.h",
|
||||||
|
"bfbs_gen_nim.cpp",
|
||||||
|
"bfbs_gen_nim.h",
|
||||||
"bfbs_namer.h",
|
"bfbs_namer.h",
|
||||||
"binary_annotator.cpp",
|
"binary_annotator.cpp",
|
||||||
"binary_annotator.h",
|
"binary_annotator.h",
|
||||||
@@ -62,6 +64,8 @@ cc_library(
|
|||||||
"bfbs_gen.h",
|
"bfbs_gen.h",
|
||||||
"bfbs_gen_lua.cpp",
|
"bfbs_gen_lua.cpp",
|
||||||
"bfbs_gen_lua.h",
|
"bfbs_gen_lua.h",
|
||||||
|
"bfbs_gen_nim.cpp",
|
||||||
|
"bfbs_gen_nim.h",
|
||||||
"bfbs_namer.h",
|
"bfbs_namer.h",
|
||||||
"flatc_main.cpp",
|
"flatc_main.cpp",
|
||||||
"idl_gen_cpp.cpp",
|
"idl_gen_cpp.cpp",
|
||||||
|
|||||||
@@ -38,8 +38,9 @@ static void ForAllObjects(
|
|||||||
for (auto it = objects->cbegin(); it != objects->cend(); ++it) { func(*it); }
|
for (auto it = objects->cbegin(); it != objects->cend(); ++it) { func(*it); }
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ForAllEnumValues(const reflection::Enum *enum_def,
|
static void ForAllEnumValues(
|
||||||
std::function<void(const reflection::EnumVal *)> func) {
|
const reflection::Enum *enum_def,
|
||||||
|
std::function<void(const reflection::EnumVal *)> func) {
|
||||||
for (auto it = enum_def->values()->cbegin(); it != enum_def->values()->cend();
|
for (auto it = enum_def->values()->cbegin(); it != enum_def->values()->cend();
|
||||||
++it) {
|
++it) {
|
||||||
func(*it);
|
func(*it);
|
||||||
@@ -91,7 +92,7 @@ static bool IsVector(const reflection::BaseType base_type) {
|
|||||||
return base_type == reflection::Vector;
|
return base_type == reflection::Vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// A concrete base Flatbuffer Generator that specific language generators can
|
// A concrete base Flatbuffer Generator that specific language generators can
|
||||||
// derive from.
|
// derive from.
|
||||||
@@ -130,17 +131,29 @@ class BaseBfbsGenerator : public BfbsGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const reflection::Object *GetObject(const reflection::Type *type) const {
|
// GetObject returns the underlying object struct of the given type
|
||||||
if (type->index() >= 0 && IsStructOrTable(type->base_type())) {
|
// if element_type is true and GetObject is a list of objects then
|
||||||
|
// GetObject will correctly return the object struct of the vector's elements
|
||||||
|
const reflection::Object *GetObject(const reflection::Type *type,
|
||||||
|
bool element_type = false) const {
|
||||||
|
const reflection::BaseType base_type =
|
||||||
|
element_type ? type->element() : type->base_type();
|
||||||
|
if (type->index() >= 0 && IsStructOrTable(base_type)) {
|
||||||
return GetObjectByIndex(type->index());
|
return GetObjectByIndex(type->index());
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const reflection::Enum *GetEnum(const reflection::Type *type) const {
|
// GetEnum returns the underlying enum struct of the given type
|
||||||
|
// if element_type is true and GetEnum is a list of enums then
|
||||||
|
// GetEnum will correctly return the enum struct of the vector's elements
|
||||||
|
const reflection::Enum *GetEnum(const reflection::Type *type,
|
||||||
|
bool element_type = false) const {
|
||||||
|
const reflection::BaseType base_type =
|
||||||
|
element_type ? type->element() : type->base_type();
|
||||||
// TODO(derekbailey): it would be better to have a explicit list of allowed
|
// TODO(derekbailey): it would be better to have a explicit list of allowed
|
||||||
// base types, instead of negating Obj types.
|
// base types, instead of negating Obj types.
|
||||||
if (type->index() >= 0 && !IsStructOrTable(type->base_type())) {
|
if (type->index() >= 0 && !IsStructOrTable(base_type)) {
|
||||||
return GetEnumByIndex(type->index());
|
return GetEnumByIndex(type->index());
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ class LuaBfbsGenerator : public BaseBfbsGenerator {
|
|||||||
// Skip writing deprecated fields altogether.
|
// Skip writing deprecated fields altogether.
|
||||||
if (field->deprecated()) { return; }
|
if (field->deprecated()) { return; }
|
||||||
|
|
||||||
const std::string field_name = namer_.Field(field->name()->str());
|
const std::string field_name = namer_.Field(*field);
|
||||||
const r::BaseType base_type = field->type()->base_type();
|
const r::BaseType base_type = field->type()->base_type();
|
||||||
|
|
||||||
// Generate some fixed strings so we don't repeat outselves later.
|
// Generate some fixed strings so we don't repeat outselves later.
|
||||||
@@ -367,9 +367,8 @@ class LuaBfbsGenerator : public BaseBfbsGenerator {
|
|||||||
ForAllFields(object, /*reverse=*/false, [&](const r::Field *field) {
|
ForAllFields(object, /*reverse=*/false, [&](const r::Field *field) {
|
||||||
if (field->deprecated()) { return; }
|
if (field->deprecated()) { return; }
|
||||||
|
|
||||||
const std::string field_name = namer_.Field(field->name()->str());
|
const std::string field_name = namer_.Field(*field);
|
||||||
const std::string variable_name =
|
const std::string variable_name = namer_.Variable(*field);
|
||||||
namer_.Variable(field->name()->str());
|
|
||||||
|
|
||||||
code += "function " + object_name + ".Add" + field_name +
|
code += "function " + object_name + ".Add" + field_name +
|
||||||
"(builder, " + variable_name + ")\n";
|
"(builder, " + variable_name + ")\n";
|
||||||
@@ -428,9 +427,9 @@ class LuaBfbsGenerator : public BaseBfbsGenerator {
|
|||||||
if (IsStructOrTable(field->type()->base_type())) {
|
if (IsStructOrTable(field->type()->base_type())) {
|
||||||
const r::Object *field_object = GetObject(field->type());
|
const r::Object *field_object = GetObject(field->type());
|
||||||
signature += GenerateStructBuilderArgs(
|
signature += GenerateStructBuilderArgs(
|
||||||
field_object, prefix + namer_.Variable(field->name()->str()) + "_");
|
field_object, prefix + namer_.Variable(*field) + "_");
|
||||||
} else {
|
} else {
|
||||||
signature += ", " + prefix + namer_.Variable(field->name()->str());
|
signature += ", " + prefix + namer_.Variable(*field);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return signature;
|
return signature;
|
||||||
@@ -451,11 +450,11 @@ class LuaBfbsGenerator : public BaseBfbsGenerator {
|
|||||||
}
|
}
|
||||||
if (IsStructOrTable(field->type()->base_type())) {
|
if (IsStructOrTable(field->type()->base_type())) {
|
||||||
const r::Object *field_object = GetObject(field->type());
|
const r::Object *field_object = GetObject(field->type());
|
||||||
code += AppendStructBuilderBody(
|
code += AppendStructBuilderBody(field_object,
|
||||||
field_object, prefix + namer_.Variable(field->name()->str()) + "_");
|
prefix + namer_.Variable(*field) + "_");
|
||||||
} else {
|
} else {
|
||||||
code += " builder:Prepend" + GenerateMethod(field) + "(" + prefix +
|
code += " builder:Prepend" + GenerateMethod(field) + "(" + prefix +
|
||||||
namer_.Variable(field->name()->str()) + ")\n";
|
namer_.Variable(*field) + ")\n";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
640
src/bfbs_gen_nim.cpp
Normal file
640
src/bfbs_gen_nim.cpp
Normal file
@@ -0,0 +1,640 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 Google Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "bfbs_gen_nim.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// Ensure no includes to flatc internals. bfbs_gen.h and generator.h are OK.
|
||||||
|
#include "bfbs_gen.h"
|
||||||
|
#include "bfbs_namer.h"
|
||||||
|
#include "flatbuffers/bfbs_generator.h"
|
||||||
|
|
||||||
|
// The intermediate representation schema.
|
||||||
|
#include "flatbuffers/reflection.h"
|
||||||
|
#include "flatbuffers/reflection_generated.h"
|
||||||
|
|
||||||
|
namespace flatbuffers {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// To reduce typing
|
||||||
|
namespace r = ::reflection;
|
||||||
|
|
||||||
|
std::set<std::string> NimKeywords() {
|
||||||
|
return {
|
||||||
|
"addr", "and", "as", "asm", "bind", "block",
|
||||||
|
"break", "case", "cast", "concept", "const", "continue",
|
||||||
|
"converter", "defer", "discard", "distinct", "div", "do",
|
||||||
|
"elif", "else", "end", "enum", "except", "export",
|
||||||
|
"finally", "for", "from", "func", "if", "import",
|
||||||
|
"in", "include", "interface", "is", "isnot", "iterator",
|
||||||
|
"let", "macro", "method", "mixin", "mod", "nil",
|
||||||
|
"not", "notin", "object", "of", "or", "out",
|
||||||
|
"proc", "ptr", "raise", "ref", "return", "shl",
|
||||||
|
"shr", "static", "template", "try", "tuple", "type",
|
||||||
|
"using", "var", "when", "while", "xor", "yield",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Namer::Config NimDefaultConfig() {
|
||||||
|
return { /*types=*/Case::kUpperCamel,
|
||||||
|
/*constants=*/Case::kUpperCamel,
|
||||||
|
/*methods=*/Case::kLowerCamel,
|
||||||
|
/*functions=*/Case::kUpperCamel,
|
||||||
|
/*fields=*/Case::kLowerCamel,
|
||||||
|
/*variable=*/Case::kLowerCamel,
|
||||||
|
/*variants=*/Case::kUpperCamel,
|
||||||
|
/*enum_variant_seperator=*/".",
|
||||||
|
/*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase,
|
||||||
|
/*namespaces=*/Case::kKeep,
|
||||||
|
/*namespace_seperator=*/"/",
|
||||||
|
/*object_prefix=*/"",
|
||||||
|
/*object_suffix=*/"T",
|
||||||
|
/*keyword_prefix=*/"",
|
||||||
|
/*keyword_suffix=*/"_",
|
||||||
|
/*filenames=*/Case::kKeep,
|
||||||
|
/*directories=*/Case::kKeep,
|
||||||
|
/*output_path=*/"",
|
||||||
|
/*filename_suffix=*/"",
|
||||||
|
/*filename_extension=*/".nim" };
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string Indent = " ";
|
||||||
|
const std::string Export = "*";
|
||||||
|
const std::set<std::string> builtin_types = {
|
||||||
|
"uint8", "uint8", "bool", "int8", "uint8", "int16",
|
||||||
|
"uint16", "int32", "uint32", "int64", "uint64", "float32",
|
||||||
|
"float64", "string", "int", "uint", "uoffset", "Builder"
|
||||||
|
};
|
||||||
|
|
||||||
|
class NimBfbsGenerator : public BaseBfbsGenerator {
|
||||||
|
public:
|
||||||
|
explicit NimBfbsGenerator(const std::string &flatc_version)
|
||||||
|
: BaseBfbsGenerator(),
|
||||||
|
keywords_(),
|
||||||
|
imports_(),
|
||||||
|
current_obj_(nullptr),
|
||||||
|
current_enum_(nullptr),
|
||||||
|
flatc_version_(flatc_version),
|
||||||
|
namer_(NimDefaultConfig(), NimKeywords()) {}
|
||||||
|
|
||||||
|
GeneratorStatus GenerateFromSchema(const r::Schema *schema)
|
||||||
|
FLATBUFFERS_OVERRIDE {
|
||||||
|
ForAllEnums(schema->enums(), [&](const r::Enum *enum_def) {
|
||||||
|
StartCodeBlock(enum_def);
|
||||||
|
GenerateEnum(enum_def);
|
||||||
|
});
|
||||||
|
ForAllObjects(schema->objects(), [&](const r::Object *object) {
|
||||||
|
StartCodeBlock(object);
|
||||||
|
GenerateObject(object);
|
||||||
|
});
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t SupportedAdvancedFeatures() const FLATBUFFERS_OVERRIDE {
|
||||||
|
return r::AdvancedArrayFeatures | r::AdvancedUnionFeatures |
|
||||||
|
r::OptionalScalars | r::DefaultVectorsAndStrings;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void GenerateEnum(const r::Enum *enum_def) {
|
||||||
|
std::string code;
|
||||||
|
|
||||||
|
std::string ns;
|
||||||
|
const std::string enum_name = namer_.Type(namer_.Denamespace(enum_def, ns));
|
||||||
|
const std::string enum_type =
|
||||||
|
GenerateTypeBasic(enum_def->underlying_type());
|
||||||
|
|
||||||
|
GenerateDocumentation(enum_def->documentation(), "", code);
|
||||||
|
code += "type " + enum_name + Export + "{.pure.} = enum\n";
|
||||||
|
|
||||||
|
ForAllEnumValues(enum_def, [&](const reflection::EnumVal *enum_val) {
|
||||||
|
GenerateDocumentation(enum_val->documentation(), " ", code);
|
||||||
|
code += " " + namer_.Variant(enum_val->name()->str()) + " = " +
|
||||||
|
NumToString(enum_val->value()) + "." + enum_type + ",\n";
|
||||||
|
});
|
||||||
|
|
||||||
|
EmitCodeBlock(code, enum_name, ns, enum_def->declaration_file()->str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenerateObject(const r::Object *object) {
|
||||||
|
// Register the main flatbuffers module.
|
||||||
|
RegisterImports("flatbuffers", "");
|
||||||
|
std::string code;
|
||||||
|
|
||||||
|
std::string ns;
|
||||||
|
const std::string object_name = namer_.Type(namer_.Denamespace(object, ns));
|
||||||
|
|
||||||
|
GenerateDocumentation(object->documentation(), "", code);
|
||||||
|
code += "type " + object_name + "* = object of FlatObj\n";
|
||||||
|
|
||||||
|
// Create all the field accessors.
|
||||||
|
ForAllFields(object, /*reverse=*/false, [&](const r::Field *field) {
|
||||||
|
// Skip writing deprecated fields altogether.
|
||||||
|
if (field->deprecated()) { return; }
|
||||||
|
|
||||||
|
const std::string field_name = namer_.Field(*field);
|
||||||
|
const r::BaseType base_type = field->type()->base_type();
|
||||||
|
std::string field_type = GenerateType(field->type());
|
||||||
|
|
||||||
|
if (field->optional() && !object->is_struct()) {
|
||||||
|
RegisterImports("std/options", "");
|
||||||
|
field_type = "Option[" + field_type + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string offset_prefix =
|
||||||
|
"let o = self.tab.Offset(" + NumToString(field->offset()) + ")\n";
|
||||||
|
const std::string offset_prefix_2 = "if o != 0:\n";
|
||||||
|
|
||||||
|
if (IsScalar(base_type) || base_type == r::String ||
|
||||||
|
base_type == r::Obj || base_type == r::Union) {
|
||||||
|
GenerateDocumentation(field->documentation(), "", code);
|
||||||
|
|
||||||
|
std::string getter_signature = "func " + namer_.Method(field_name) +
|
||||||
|
"*(self: " + object_name +
|
||||||
|
"): " + field_type + " =\n";
|
||||||
|
std::string getter_code;
|
||||||
|
std::string setter_signature =
|
||||||
|
"func `" + namer_.Method(field_name + "=") + "`*(self: var " +
|
||||||
|
object_name + ", n: " + field_type + "): bool =\n";
|
||||||
|
std::string setter_code;
|
||||||
|
|
||||||
|
if (base_type == r::Obj || base_type == r::Union ||
|
||||||
|
field->type()->index() >= 0) {
|
||||||
|
RegisterImports(object, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (object->is_struct()) {
|
||||||
|
std::string field_getter =
|
||||||
|
GenerateGetter(field->type(), NumToString(field->offset()));
|
||||||
|
getter_code += " return " + field_getter + "\n";
|
||||||
|
|
||||||
|
if (IsScalar(base_type)) {
|
||||||
|
setter_code += " return self.tab.Mutate(self.tab.Pos + " +
|
||||||
|
NumToString(field->offset()) + ", n)\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Table accessors
|
||||||
|
getter_code += " " + offset_prefix;
|
||||||
|
getter_code += " " + offset_prefix_2;
|
||||||
|
std::string field_getter = GenerateGetter(field->type(), "o");
|
||||||
|
if (field->optional()) {
|
||||||
|
field_getter = "some(" + field_getter + ")";
|
||||||
|
}
|
||||||
|
getter_code += " return " + field_getter + "\n";
|
||||||
|
if (!field->optional()) {
|
||||||
|
getter_code += " return " + DefaultValue(field) + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsScalar(base_type)) {
|
||||||
|
setter_code += " return self.tab.MutateSlot(" +
|
||||||
|
NumToString(field->offset()) + ", n)\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
code += getter_signature + getter_code;
|
||||||
|
if (IsScalar(base_type)) { code += setter_signature + setter_code; }
|
||||||
|
} else if (base_type == r::Array || base_type == r::Vector) {
|
||||||
|
const r::BaseType vector_base_type = field->type()->element();
|
||||||
|
uint32_t element_size = field->type()->element_size();
|
||||||
|
|
||||||
|
if (vector_base_type == r::Obj || vector_base_type == r::Union ||
|
||||||
|
field->type()->index() >= 0) {
|
||||||
|
RegisterImports(object, field, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get vector length:
|
||||||
|
code += "func " + namer_.Method(field_name + "Length") +
|
||||||
|
"*(self: " + object_name + "): int = \n";
|
||||||
|
code += " " + offset_prefix;
|
||||||
|
code += " " + offset_prefix_2;
|
||||||
|
code += " return self.tab.VectorLen(o)\n";
|
||||||
|
|
||||||
|
// Get single vector field:
|
||||||
|
code += "func " + namer_.Method(field_name) + "*(self: " + object_name +
|
||||||
|
", j: int): " + GenerateType(field->type(), true) + " = \n";
|
||||||
|
code += " " + offset_prefix;
|
||||||
|
code += " " + offset_prefix_2;
|
||||||
|
code += " var x = self.tab.Vector(o)\n";
|
||||||
|
code +=
|
||||||
|
" x += j.uoffset * " + NumToString(element_size) + ".uoffset\n";
|
||||||
|
code += " return " + GenerateGetter(field->type(), "x", true) + "\n";
|
||||||
|
|
||||||
|
// Get entire vector:
|
||||||
|
code += "func " + namer_.Method(field_name) + "*(self: " + object_name +
|
||||||
|
"): " + GenerateType(field->type()) + " = \n";
|
||||||
|
code += " let len = self." + field_name + "Length\n";
|
||||||
|
code += " for i in countup(0, len - 1):\n";
|
||||||
|
code += " result.add(self." + field_name + "(i))\n";
|
||||||
|
|
||||||
|
(void)IsSingleByte(vector_base_type); // unnused function warning
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create all the builders
|
||||||
|
if (object->is_struct()) {
|
||||||
|
code += "proc " + namer_.Function(object_name + "Create") +
|
||||||
|
"*(self: var Builder";
|
||||||
|
code += GenerateStructBuilderArgs(object);
|
||||||
|
code += "): uoffset =\n";
|
||||||
|
code += AppendStructBuilderBody(object);
|
||||||
|
code += " return self.Offset()\n";
|
||||||
|
} else {
|
||||||
|
// Table builders
|
||||||
|
code += "proc " + namer_.Function(object_name + "Start") +
|
||||||
|
"*(builder: var Builder) =\n";
|
||||||
|
code += " builder.StartObject(" + NumToString(object->fields()->size()) +
|
||||||
|
")\n";
|
||||||
|
|
||||||
|
ForAllFields(object, /*reverse=*/false, [&](const r::Field *field) {
|
||||||
|
if (field->deprecated()) { return; }
|
||||||
|
|
||||||
|
const std::string field_name = namer_.Field(*field);
|
||||||
|
const std::string variable_name = namer_.Variable(*field);
|
||||||
|
const std::string variable_type = GenerateTypeBasic(field->type());
|
||||||
|
|
||||||
|
code += "proc " + namer_.Function(object_name + "Add" + field_name) +
|
||||||
|
"*(builder: var Builder, " + variable_name + ": " +
|
||||||
|
variable_type + ") =\n";
|
||||||
|
code += " builder.Prepend" + GenerateMethod(field) + "Slot(" +
|
||||||
|
NumToString(field->id()) + ", " + variable_name + ", default(" +
|
||||||
|
variable_type + "))\n";
|
||||||
|
|
||||||
|
if (IsVector(field->type()->base_type())) {
|
||||||
|
code += "proc " +
|
||||||
|
namer_.Function(object_name + "Start" + field_name) +
|
||||||
|
"Vector*(builder: var Builder, numElems: uoffset) =\n";
|
||||||
|
|
||||||
|
const int32_t element_size = field->type()->element_size();
|
||||||
|
int32_t alignment = element_size;
|
||||||
|
if (IsStruct(field->type(), /*use_element=*/true)) {
|
||||||
|
alignment = GetObjectByIndex(field->type()->index())->minalign();
|
||||||
|
}
|
||||||
|
|
||||||
|
code += " builder.StartVector(" + NumToString(element_size) +
|
||||||
|
", numElems, " + NumToString(alignment) + ")\n";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
code += "proc " + namer_.Function(object_name + "End") +
|
||||||
|
"*(builder: var Builder): uoffset =\n";
|
||||||
|
code += " return builder.EndObject()\n";
|
||||||
|
}
|
||||||
|
EmitCodeBlock(code, object_name, ns, object->declaration_file()->str());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void GenerateDocumentation(
|
||||||
|
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>
|
||||||
|
*documentation,
|
||||||
|
std::string indent, std::string &code) const {
|
||||||
|
flatbuffers::ForAllDocumentation(
|
||||||
|
documentation, [&](const flatbuffers::String *str) {
|
||||||
|
code += indent + "# " + str->str() + "\n";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GenerateStructBuilderArgs(const r::Object *object,
|
||||||
|
std::string prefix = "") const {
|
||||||
|
std::string signature;
|
||||||
|
ForAllFields(object, /*reverse=*/false, [&](const r::Field *field) {
|
||||||
|
if (IsStructOrTable(field->type()->base_type())) {
|
||||||
|
const r::Object *field_object = GetObject(field->type());
|
||||||
|
signature += GenerateStructBuilderArgs(
|
||||||
|
field_object, prefix + namer_.Variable(*field) + "_");
|
||||||
|
} else {
|
||||||
|
signature += ", " + prefix + namer_.Variable(*field) + ": " +
|
||||||
|
GenerateType(field->type());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AppendStructBuilderBody(const r::Object *object,
|
||||||
|
std::string prefix = "") const {
|
||||||
|
std::string code;
|
||||||
|
code += " self.Prep(" + NumToString(object->minalign()) + ", " +
|
||||||
|
NumToString(object->bytesize()) + ")\n";
|
||||||
|
|
||||||
|
// We need to reverse the order we iterate over, since we build the
|
||||||
|
// buffer backwards.
|
||||||
|
ForAllFields(object, /*reverse=*/true, [&](const r::Field *field) {
|
||||||
|
const int32_t num_padding_bytes = field->padding();
|
||||||
|
if (num_padding_bytes) {
|
||||||
|
code += " self.Pad(" + NumToString(num_padding_bytes) + ")\n";
|
||||||
|
}
|
||||||
|
if (IsStructOrTable(field->type()->base_type())) {
|
||||||
|
const r::Object *field_object = GetObject(field->type());
|
||||||
|
code += AppendStructBuilderBody(field_object,
|
||||||
|
prefix + namer_.Variable(*field) + "_");
|
||||||
|
} else {
|
||||||
|
code += " self.Prepend(" + prefix + namer_.Variable(*field) + ")\n";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GenerateMethod(const r::Field *field) const {
|
||||||
|
const r::BaseType base_type = field->type()->base_type();
|
||||||
|
if (IsStructOrTable(base_type)) { return "Struct"; }
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GenerateGetter(const r::Type *type, const std::string &offsetval,
|
||||||
|
bool element_type = false) const {
|
||||||
|
const r::BaseType base_type =
|
||||||
|
element_type ? type->element() : type->base_type();
|
||||||
|
std::string offset = offsetval;
|
||||||
|
if (!element_type) { offset = "self.tab.Pos + " + offset; }
|
||||||
|
switch (base_type) {
|
||||||
|
case r::String: return "self.tab.String(" + offset + ")";
|
||||||
|
case r::Union: return "self.tab.Union(" + offsetval + ")";
|
||||||
|
case r::Obj: {
|
||||||
|
return GenerateType(type, element_type) +
|
||||||
|
"(tab: Vtable(Bytes: self.tab.Bytes, Pos: " + offset + "))";
|
||||||
|
}
|
||||||
|
case r::Vector: return GenerateGetter(type, offsetval, true);
|
||||||
|
default:
|
||||||
|
const r::Enum *type_enum = GetEnum(type, element_type);
|
||||||
|
if (type_enum != nullptr) {
|
||||||
|
return GenerateType(type, element_type) + "(" + "Get[" +
|
||||||
|
GenerateType(base_type) + "](self.tab, " + offset + ")" + ")";
|
||||||
|
} else {
|
||||||
|
return "Get[" + GenerateType(base_type) + "](self.tab, " + offset +
|
||||||
|
")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Denamespace(const std::string &s, std::string &importns,
|
||||||
|
std::string &ns) const {
|
||||||
|
if (builtin_types.find(s) != builtin_types.end()) { return s; }
|
||||||
|
std::string type = namer_.Type(namer_.Denamespace(s, ns));
|
||||||
|
importns = ns.empty() ? type : ns + "." + type;
|
||||||
|
std::replace(importns.begin(), importns.end(), '.', '_');
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Denamespace(const std::string &s, std::string &importns) const {
|
||||||
|
std::string ns;
|
||||||
|
return Denamespace(s, importns, ns);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Denamespace(const std::string &s) const {
|
||||||
|
std::string importns;
|
||||||
|
return Denamespace(s, importns);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GenerateType(const r::Type *type, bool element_type = false,
|
||||||
|
bool enum_inner = false) const {
|
||||||
|
const r::BaseType base_type =
|
||||||
|
element_type ? type->element() : type->base_type();
|
||||||
|
if (IsScalar(base_type) && !enum_inner) {
|
||||||
|
const r::Enum *type_enum = GetEnum(type, element_type);
|
||||||
|
if (type_enum != nullptr) {
|
||||||
|
std::string importns;
|
||||||
|
std::string type_name = Denamespace(type_enum->name()->str(), importns);
|
||||||
|
return importns + "." + type_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (IsScalar(base_type)) { return Denamespace(GenerateType(base_type)); }
|
||||||
|
switch (base_type) {
|
||||||
|
case r::String: return "string";
|
||||||
|
case r::Vector: {
|
||||||
|
return "seq[" + GenerateType(type, true) + "]";
|
||||||
|
}
|
||||||
|
case r::Union: return "Vtable";
|
||||||
|
case r::Obj: {
|
||||||
|
const r::Object *type_obj = GetObject(type, element_type);
|
||||||
|
std::string importns;
|
||||||
|
std::string type_name = Denamespace(type_obj->name()->str(), importns);
|
||||||
|
if (type_obj == current_obj_) {
|
||||||
|
return type_name;
|
||||||
|
} else {
|
||||||
|
return importns + "." + type_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default: return "uoffset";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GenerateTypeBasic(const r::Type *type,
|
||||||
|
bool element_type = false) const {
|
||||||
|
const r::BaseType base_type =
|
||||||
|
element_type ? type->element() : type->base_type();
|
||||||
|
if (IsScalar(base_type)) {
|
||||||
|
return GenerateType(base_type);
|
||||||
|
} else {
|
||||||
|
return "uoffset";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GenerateType(const r::BaseType base_type) const {
|
||||||
|
switch (base_type) {
|
||||||
|
case r::None: return "uint8";
|
||||||
|
case r::UType: return "uint8";
|
||||||
|
case r::Bool: return "bool";
|
||||||
|
case r::Byte: return "int8";
|
||||||
|
case r::UByte: return "uint8";
|
||||||
|
case r::Short: return "int16";
|
||||||
|
case r::UShort: return "uint16";
|
||||||
|
case r::Int: return "int32";
|
||||||
|
case r::UInt: return "uint32";
|
||||||
|
case r::Long: return "int64";
|
||||||
|
case r::ULong: return "uint64";
|
||||||
|
case r::Float: return "float32";
|
||||||
|
case r::Double: return "float64";
|
||||||
|
case r::String: return "string";
|
||||||
|
default: return r::EnumNameBaseType(base_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DefaultValue(const r::Field *field) const {
|
||||||
|
const r::BaseType base_type = field->type()->base_type();
|
||||||
|
if (IsFloatingPoint(base_type)) {
|
||||||
|
return NumToString(field->default_real());
|
||||||
|
}
|
||||||
|
if (IsBool(base_type)) {
|
||||||
|
return field->default_integer() ? "true" : "false";
|
||||||
|
}
|
||||||
|
if (IsScalar(base_type)) {
|
||||||
|
const r::Enum *type_enum = GetEnum(field->type());
|
||||||
|
if (type_enum != nullptr) {
|
||||||
|
return "type(result)(" + NumToString((field->default_integer())) + ")";
|
||||||
|
}
|
||||||
|
return NumToString((field->default_integer()));
|
||||||
|
}
|
||||||
|
if (base_type == r::String) { return "\"\""; }
|
||||||
|
// represents offsets
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartCodeBlock(const reflection::Enum *enum_def) {
|
||||||
|
current_enum_ = enum_def;
|
||||||
|
current_obj_ = nullptr;
|
||||||
|
imports_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartCodeBlock(const reflection::Object *object) {
|
||||||
|
current_enum_ = nullptr;
|
||||||
|
current_obj_ = object;
|
||||||
|
imports_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> StringSplit(const std::string orig_str,
|
||||||
|
const std::string token) {
|
||||||
|
std::vector<std::string> result;
|
||||||
|
std::string str = orig_str;
|
||||||
|
while (str.size()) {
|
||||||
|
size_t index = str.find(token);
|
||||||
|
if (index != std::string::npos) {
|
||||||
|
result.push_back(str.substr(0, index));
|
||||||
|
str = str.substr(index + token.size());
|
||||||
|
if (str.size() == 0) result.push_back(str);
|
||||||
|
} else {
|
||||||
|
result.push_back(str);
|
||||||
|
str = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetRelativePathFromNamespace(const std::string &relative_to,
|
||||||
|
const std::string &str2) {
|
||||||
|
std::vector<std::string> relative_to_vec = StringSplit(relative_to, ".");
|
||||||
|
std::vector<std::string> str2_vec = StringSplit(str2, ".");
|
||||||
|
while (relative_to_vec.size() > 0 && str2_vec.size() > 0) {
|
||||||
|
if (relative_to_vec[0] == str2_vec[0]) {
|
||||||
|
relative_to_vec.erase(relative_to_vec.begin());
|
||||||
|
str2_vec.erase(str2_vec.begin());
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
relative_to_vec.pop_back();
|
||||||
|
for (size_t i = 0; i < relative_to_vec.size(); ++i) {
|
||||||
|
str2_vec.insert(str2_vec.begin(), std::string(".."));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string new_path;
|
||||||
|
for (size_t i = 0; i < str2_vec.size(); ++i) {
|
||||||
|
new_path += str2_vec[i];
|
||||||
|
if (i != str2_vec.size() - 1) { new_path += "/"; }
|
||||||
|
}
|
||||||
|
return new_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterImports(const r::Object *object, const r::Field *field,
|
||||||
|
bool use_element = false) {
|
||||||
|
std::string importns;
|
||||||
|
std::string type_name;
|
||||||
|
|
||||||
|
const r::BaseType type =
|
||||||
|
use_element ? field->type()->element() : field->type()->base_type();
|
||||||
|
|
||||||
|
if (IsStructOrTable(type)) {
|
||||||
|
const r::Object *object_def = GetObjectByIndex(field->type()->index());
|
||||||
|
if (object_def == current_obj_) { return; }
|
||||||
|
std::string ns;
|
||||||
|
type_name = Denamespace(object_def->name()->str(), importns, ns);
|
||||||
|
type_name = ns.empty() ? type_name : ns + "." + type_name;
|
||||||
|
} else {
|
||||||
|
const r::Enum *enum_def = GetEnumByIndex(field->type()->index());
|
||||||
|
if (enum_def == current_enum_) { return; }
|
||||||
|
std::string ns;
|
||||||
|
type_name = Denamespace(enum_def->name()->str(), importns, ns);
|
||||||
|
type_name = ns.empty() ? type_name : ns + "." + type_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string import_path =
|
||||||
|
GetRelativePathFromNamespace(object->name()->str(), type_name);
|
||||||
|
std::replace(type_name.begin(), type_name.end(), '.', '_');
|
||||||
|
RegisterImports(import_path, importns);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterImports(const std::string &local_name,
|
||||||
|
const std::string &imports_name) {
|
||||||
|
imports_[local_name] = imports_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitCodeBlock(const std::string &code_block, const std::string &name,
|
||||||
|
const std::string &ns, const std::string &declaring_file) {
|
||||||
|
const std::string full_qualified_name = ns.empty() ? name : ns + "." + name;
|
||||||
|
|
||||||
|
std::string code = "#[ " + full_qualified_name + "\n";
|
||||||
|
code +=
|
||||||
|
" Automatically generated by the FlatBuffers compiler, do not "
|
||||||
|
"modify.\n";
|
||||||
|
code += " Or modify. I'm a message, not a cop.\n";
|
||||||
|
code += "\n";
|
||||||
|
code += " flatc version: " + flatc_version_ + "\n";
|
||||||
|
code += "\n";
|
||||||
|
code += " Declared by : " + declaring_file + "\n";
|
||||||
|
if (schema_->root_table() != nullptr) {
|
||||||
|
const std::string root_type = schema_->root_table()->name()->str();
|
||||||
|
const std::string root_file =
|
||||||
|
schema_->root_table()->declaration_file()->str();
|
||||||
|
code += " Rooting type : " + root_type + " (" + root_file + ")\n";
|
||||||
|
}
|
||||||
|
code += "]#\n\n";
|
||||||
|
|
||||||
|
if (!imports_.empty()) {
|
||||||
|
for (auto it = imports_.cbegin(); it != imports_.cend(); ++it) {
|
||||||
|
if (it->second.empty()) {
|
||||||
|
code += "import " + it->first + "\n";
|
||||||
|
} else {
|
||||||
|
code += "import " + it->first + " as " + it->second + "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
code += "\n";
|
||||||
|
}
|
||||||
|
code += code_block;
|
||||||
|
|
||||||
|
// Namespaces are '.' deliminted, so replace it with the path separator.
|
||||||
|
std::string path = ns;
|
||||||
|
|
||||||
|
if (ns.empty()) {
|
||||||
|
path = ".";
|
||||||
|
} else {
|
||||||
|
std::replace(path.begin(), path.end(), '.', '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(derekbailey): figure out a save file without depending on util.h
|
||||||
|
EnsureDirExists(path);
|
||||||
|
const std::string file_name = path + "/" + namer_.File(name);
|
||||||
|
SaveFile(file_name.c_str(), code, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_set<std::string> keywords_;
|
||||||
|
std::map<std::string, std::string> imports_;
|
||||||
|
const r::Object *current_obj_;
|
||||||
|
const r::Enum *current_enum_;
|
||||||
|
const std::string flatc_version_;
|
||||||
|
const BfbsNamer namer_;
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
std::unique_ptr<BfbsGenerator> NewNimBfbsGenerator(
|
||||||
|
const std::string &flatc_version) {
|
||||||
|
return std::unique_ptr<NimBfbsGenerator>(new NimBfbsGenerator(flatc_version));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace flatbuffers
|
||||||
33
src/bfbs_gen_nim.h
Normal file
33
src/bfbs_gen_nim.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 Google Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FLATBUFFERS_BFBS_GEN_NIM_H_
|
||||||
|
#define FLATBUFFERS_BFBS_GEN_NIM_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "flatbuffers/bfbs_generator.h"
|
||||||
|
|
||||||
|
namespace flatbuffers {
|
||||||
|
|
||||||
|
// Constructs a new Nim Code generator.
|
||||||
|
std::unique_ptr<BfbsGenerator> NewNimBfbsGenerator(
|
||||||
|
const std::string &flatc_version);
|
||||||
|
|
||||||
|
} // namespace flatbuffers
|
||||||
|
|
||||||
|
#endif // FLATBUFFERS_BFBS_GEN_NIM_H_
|
||||||
@@ -36,6 +36,14 @@ class BfbsNamer : public Namer {
|
|||||||
std::string Denamespace(T t, const char delimiter = '.') const {
|
std::string Denamespace(T t, const char delimiter = '.') const {
|
||||||
return Namer::Denamespace(t->name()->c_str(), delimiter);
|
return Namer::Denamespace(t->name()->c_str(), delimiter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual std::string Field(const ::reflection::Field &f) const {
|
||||||
|
return Field(f.name()->str());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::string Variable(const ::reflection::Field &f) const {
|
||||||
|
return Variable(f.name()->str());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace flatbuffers
|
} // namespace flatbuffers
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "bfbs_gen_lua.h"
|
#include "bfbs_gen_lua.h"
|
||||||
|
#include "bfbs_gen_nim.h"
|
||||||
#include "flatbuffers/base.h"
|
#include "flatbuffers/base.h"
|
||||||
#include "flatbuffers/flatc.h"
|
#include "flatbuffers/flatc.h"
|
||||||
#include "flatbuffers/util.h"
|
#include "flatbuffers/util.h"
|
||||||
@@ -56,6 +57,8 @@ int main(int argc, const char *argv[]) {
|
|||||||
|
|
||||||
std::unique_ptr<flatbuffers::BfbsGenerator> bfbs_gen_lua =
|
std::unique_ptr<flatbuffers::BfbsGenerator> bfbs_gen_lua =
|
||||||
flatbuffers::NewLuaBfbsGenerator(flatbuffers_version);
|
flatbuffers::NewLuaBfbsGenerator(flatbuffers_version);
|
||||||
|
std::unique_ptr<flatbuffers::BfbsGenerator> bfbs_gen_nim =
|
||||||
|
flatbuffers::NewNimBfbsGenerator(flatbuffers_version);
|
||||||
|
|
||||||
g_program_name = argv[0];
|
g_program_name = argv[0];
|
||||||
|
|
||||||
@@ -142,6 +145,10 @@ int main(int argc, const char *argv[]) {
|
|||||||
flatbuffers::FlatCOption{ "", "swift", "",
|
flatbuffers::FlatCOption{ "", "swift", "",
|
||||||
"Generate Swift files for tables/structs" },
|
"Generate Swift files for tables/structs" },
|
||||||
nullptr, nullptr, nullptr },
|
nullptr, nullptr, nullptr },
|
||||||
|
{ nullptr, "Nim", true, nullptr, flatbuffers::IDLOptions::kNim,
|
||||||
|
flatbuffers::FlatCOption{ "", "nim", "",
|
||||||
|
"Generate Nim files for tables/structs" },
|
||||||
|
nullptr, bfbs_gen_nim.get(), nullptr },
|
||||||
};
|
};
|
||||||
|
|
||||||
flatbuffers::FlatCompiler::InitParams params;
|
flatbuffers::FlatCompiler::InitParams params;
|
||||||
|
|||||||
@@ -655,7 +655,7 @@ class CSharpGenerator : public BaseGenerator {
|
|||||||
// Force compile time error if not using the same version runtime.
|
// Force compile time error if not using the same version runtime.
|
||||||
code += " public static void ValidateVersion() {";
|
code += " public static void ValidateVersion() {";
|
||||||
code += " FlatBufferConstants.";
|
code += " FlatBufferConstants.";
|
||||||
code += "FLATBUFFERS_22_9_24(); ";
|
code += "FLATBUFFERS_22_10_25(); ";
|
||||||
code += "}\n";
|
code += "}\n";
|
||||||
|
|
||||||
// Generate a special accessor for the table that when used as the root
|
// Generate a special accessor for the table that when used as the root
|
||||||
|
|||||||
@@ -397,6 +397,10 @@ class JavaGenerator : public BaseGenerator {
|
|||||||
code += " ";
|
code += " ";
|
||||||
code += namer_.Variant(ev) + " = ";
|
code += namer_.Variant(ev) + " = ";
|
||||||
code += enum_def.ToString(ev);
|
code += enum_def.ToString(ev);
|
||||||
|
if (enum_def.underlying_type.base_type == BASE_TYPE_LONG ||
|
||||||
|
enum_def.underlying_type.base_type == BASE_TYPE_ULONG) {
|
||||||
|
code += "L";
|
||||||
|
}
|
||||||
code += ";\n";
|
code += ";\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -665,7 +669,7 @@ class JavaGenerator : public BaseGenerator {
|
|||||||
// Force compile time error if not using the same version runtime.
|
// Force compile time error if not using the same version runtime.
|
||||||
code += " public static void ValidateVersion() {";
|
code += " public static void ValidateVersion() {";
|
||||||
code += " Constants.";
|
code += " Constants.";
|
||||||
code += "FLATBUFFERS_22_9_24(); ";
|
code += "FLATBUFFERS_22_10_25(); ";
|
||||||
code += "}\n";
|
code += "}\n";
|
||||||
|
|
||||||
// Generate a special accessor for the table that when used as the root
|
// Generate a special accessor for the table that when used as the root
|
||||||
@@ -1889,6 +1893,7 @@ class JavaGenerator : public BaseGenerator {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
code += " " + name + " = ";
|
code += " " + name + " = ";
|
||||||
|
code += SourceCast(field_type);
|
||||||
code += "_o";
|
code += "_o";
|
||||||
for (size_t i = 0; i < array_lengths.size(); ++i) {
|
for (size_t i = 0; i < array_lengths.size(); ++i) {
|
||||||
code += "." + namer_.Method("get", array_lengths[i].name) + "()";
|
code += "." + namer_.Method("get", array_lengths[i].name) + "()";
|
||||||
|
|||||||
@@ -505,7 +505,7 @@ class KotlinGenerator : public BaseGenerator {
|
|||||||
// runtime.
|
// runtime.
|
||||||
GenerateFunOneLine(
|
GenerateFunOneLine(
|
||||||
writer, "validateVersion", "", "",
|
writer, "validateVersion", "", "",
|
||||||
[&]() { writer += "Constants.FLATBUFFERS_22_9_24()"; },
|
[&]() { writer += "Constants.FLATBUFFERS_22_10_25()"; },
|
||||||
options.gen_jvmstatic);
|
options.gen_jvmstatic);
|
||||||
|
|
||||||
GenerateGetRootAsAccessors(namer_.Type(struct_def), writer, options);
|
GenerateGetRootAsAccessors(namer_.Type(struct_def), writer, options);
|
||||||
|
|||||||
@@ -737,7 +737,6 @@ class RustGenerator : public BaseGenerator {
|
|||||||
code_ += "pub use self::bitflags_{{ENUM_NAMESPACE}}::{{ENUM_TY}};";
|
code_ += "pub use self::bitflags_{{ENUM_NAMESPACE}}::{{ENUM_TY}};";
|
||||||
code_ += "";
|
code_ += "";
|
||||||
|
|
||||||
code_.SetValue("FROM_BASE", "unsafe { Self::from_bits_unchecked(b) }");
|
|
||||||
code_.SetValue("INTO_BASE", "self.bits()");
|
code_.SetValue("INTO_BASE", "self.bits()");
|
||||||
} else {
|
} else {
|
||||||
// Normal, c-modelled enums.
|
// Normal, c-modelled enums.
|
||||||
@@ -810,7 +809,6 @@ class RustGenerator : public BaseGenerator {
|
|||||||
code_ += " }";
|
code_ += " }";
|
||||||
code_ += "}";
|
code_ += "}";
|
||||||
|
|
||||||
code_.SetValue("FROM_BASE", "Self(b)");
|
|
||||||
code_.SetValue("INTO_BASE", "self.0");
|
code_.SetValue("INTO_BASE", "self.0");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -839,35 +837,55 @@ class RustGenerator : public BaseGenerator {
|
|||||||
code_ += "impl<'a> flatbuffers::Follow<'a> for {{ENUM_TY}} {";
|
code_ += "impl<'a> flatbuffers::Follow<'a> for {{ENUM_TY}} {";
|
||||||
code_ += " type Inner = Self;";
|
code_ += " type Inner = Self;";
|
||||||
code_ += " #[inline]";
|
code_ += " #[inline]";
|
||||||
code_ += " fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
|
code_ += " unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
|
||||||
code_ += " let b = unsafe {";
|
code_ += " let b = flatbuffers::read_scalar_at::<{{BASE_TYPE}}>(buf, loc);";
|
||||||
code_ += " flatbuffers::read_scalar_at::<{{BASE_TYPE}}>(buf, loc)";
|
if (IsBitFlagsEnum(enum_def)) {
|
||||||
code_ += " };";
|
// Safety:
|
||||||
code_ += " {{FROM_BASE}}";
|
// This is safe because we know bitflags is implemented with a repr transparent uint of the correct size.
|
||||||
|
// from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0
|
||||||
|
// https://github.com/bitflags/bitflags/issues/262
|
||||||
|
code_ += " // Safety:";
|
||||||
|
code_ += " // This is safe because we know bitflags is implemented with a repr transparent uint of the correct size.";
|
||||||
|
code_ += " // from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0";
|
||||||
|
code_ += " // https://github.com/bitflags/bitflags/issues/262";
|
||||||
|
code_ += " Self::from_bits_unchecked(b)";
|
||||||
|
} else {
|
||||||
|
code_ += " Self(b)";
|
||||||
|
}
|
||||||
code_ += " }";
|
code_ += " }";
|
||||||
code_ += "}";
|
code_ += "}";
|
||||||
code_ += "";
|
code_ += "";
|
||||||
code_ += "impl flatbuffers::Push for {{ENUM_TY}} {";
|
code_ += "impl flatbuffers::Push for {{ENUM_TY}} {";
|
||||||
code_ += " type Output = {{ENUM_TY}};";
|
code_ += " type Output = {{ENUM_TY}};";
|
||||||
code_ += " #[inline]";
|
code_ += " #[inline]";
|
||||||
code_ += " fn push(&self, dst: &mut [u8], _rest: &[u8]) {";
|
code_ += " unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {";
|
||||||
code_ +=
|
code_ += " flatbuffers::emplace_scalar::<{{BASE_TYPE}}>(dst, {{INTO_BASE}});";
|
||||||
" unsafe { flatbuffers::emplace_scalar::<{{BASE_TYPE}}>"
|
|
||||||
"(dst, {{INTO_BASE}}); }";
|
|
||||||
code_ += " }";
|
code_ += " }";
|
||||||
code_ += "}";
|
code_ += "}";
|
||||||
code_ += "";
|
code_ += "";
|
||||||
code_ += "impl flatbuffers::EndianScalar for {{ENUM_TY}} {";
|
code_ += "impl flatbuffers::EndianScalar for {{ENUM_TY}} {";
|
||||||
|
code_ += " type Scalar = {{BASE_TYPE}};";
|
||||||
code_ += " #[inline]";
|
code_ += " #[inline]";
|
||||||
code_ += " fn to_little_endian(self) -> Self {";
|
code_ += " fn to_little_endian(self) -> {{BASE_TYPE}} {";
|
||||||
code_ += " let b = {{BASE_TYPE}}::to_le({{INTO_BASE}});";
|
code_ += " {{INTO_BASE}}.to_le()";
|
||||||
code_ += " {{FROM_BASE}}";
|
|
||||||
code_ += " }";
|
code_ += " }";
|
||||||
code_ += " #[inline]";
|
code_ += " #[inline]";
|
||||||
code_ += " #[allow(clippy::wrong_self_convention)]";
|
code_ += " #[allow(clippy::wrong_self_convention)]";
|
||||||
code_ += " fn from_little_endian(self) -> Self {";
|
code_ += " fn from_little_endian(v: {{BASE_TYPE}}) -> Self {";
|
||||||
code_ += " let b = {{BASE_TYPE}}::from_le({{INTO_BASE}});";
|
code_ += " let b = {{BASE_TYPE}}::from_le(v);";
|
||||||
code_ += " {{FROM_BASE}}";
|
if (IsBitFlagsEnum(enum_def)) {
|
||||||
|
// Safety:
|
||||||
|
// This is safe because we know bitflags is implemented with a repr transparent uint of the correct size.
|
||||||
|
// from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0
|
||||||
|
// https://github.com/bitflags/bitflags/issues/262
|
||||||
|
code_ += " // Safety:";
|
||||||
|
code_ += " // This is safe because we know bitflags is implemented with a repr transparent uint of the correct size.";
|
||||||
|
code_ += " // from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0";
|
||||||
|
code_ += " // https://github.com/bitflags/bitflags/issues/262";
|
||||||
|
code_ += " unsafe { Self::from_bits_unchecked(b) }";
|
||||||
|
} else {
|
||||||
|
code_ += " Self(b)";
|
||||||
|
}
|
||||||
code_ += " }";
|
code_ += " }";
|
||||||
code_ += "}";
|
code_ += "}";
|
||||||
code_ += "";
|
code_ += "";
|
||||||
@@ -1425,11 +1443,7 @@ class RustGenerator : public BaseGenerator {
|
|||||||
case ftVectorOfBool:
|
case ftVectorOfBool:
|
||||||
case ftVectorOfFloat: {
|
case ftVectorOfFloat: {
|
||||||
const auto typname = GetTypeBasic(type.VectorType());
|
const auto typname = GetTypeBasic(type.VectorType());
|
||||||
const auto vector_type =
|
return WrapOption("flatbuffers::Vector<" + lifetime + ", " + typname + ">");
|
||||||
IsOneByte(type.VectorType().base_type)
|
|
||||||
? "&" + lifetime + " [" + typname + "]"
|
|
||||||
: "flatbuffers::Vector<" + lifetime + ", " + typname + ">";
|
|
||||||
return WrapOption(vector_type);
|
|
||||||
}
|
}
|
||||||
case ftVectorOfEnumKey: {
|
case ftVectorOfEnumKey: {
|
||||||
const auto typname = WrapInNameSpace(*type.enum_def);
|
const auto typname = WrapInNameSpace(*type.enum_def);
|
||||||
@@ -1438,7 +1452,7 @@ class RustGenerator : public BaseGenerator {
|
|||||||
}
|
}
|
||||||
case ftVectorOfStruct: {
|
case ftVectorOfStruct: {
|
||||||
const auto typname = WrapInNameSpace(*type.struct_def);
|
const auto typname = WrapInNameSpace(*type.struct_def);
|
||||||
return WrapOption("&" + lifetime + " [" + typname + "]");
|
return WrapOption("flatbuffers::Vector<" + lifetime + ", " + typname + ">");
|
||||||
}
|
}
|
||||||
case ftVectorOfTable: {
|
case ftVectorOfTable: {
|
||||||
const auto typname = WrapInNameSpace(*type.struct_def);
|
const auto typname = WrapInNameSpace(*type.struct_def);
|
||||||
@@ -1556,19 +1570,8 @@ class RustGenerator : public BaseGenerator {
|
|||||||
: "None";
|
: "None";
|
||||||
const std::string unwrap = field.IsOptional() ? "" : ".unwrap()";
|
const std::string unwrap = field.IsOptional() ? "" : ".unwrap()";
|
||||||
|
|
||||||
const auto t = GetFullType(field.value.type);
|
return "unsafe { self._tab.get::<" + typname + ">({{STRUCT_TY}}::" + vt_offset +
|
||||||
|
", " + default_value + ")" + unwrap + "}";
|
||||||
// TODO(caspern): Shouldn't 1byte VectorOfEnumKey be slice too?
|
|
||||||
const std::string safe_slice =
|
|
||||||
(t == ftVectorOfStruct ||
|
|
||||||
((t == ftVectorOfBool || t == ftVectorOfFloat ||
|
|
||||||
t == ftVectorOfInteger) &&
|
|
||||||
IsOneByte(field.value.type.VectorType().base_type)))
|
|
||||||
? ".map(|v| v.safe_slice())"
|
|
||||||
: "";
|
|
||||||
|
|
||||||
return "self._tab.get::<" + typname + ">({{STRUCT_TY}}::" + vt_offset +
|
|
||||||
", " + default_value + ")" + safe_slice + unwrap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generates a fully-qualified name getter for use with --gen-name-strings
|
// Generates a fully-qualified name getter for use with --gen-name-strings
|
||||||
@@ -1650,8 +1653,8 @@ class RustGenerator : public BaseGenerator {
|
|||||||
code_ += "impl<'a> flatbuffers::Follow<'a> for {{STRUCT_TY}}<'a> {";
|
code_ += "impl<'a> flatbuffers::Follow<'a> for {{STRUCT_TY}}<'a> {";
|
||||||
code_ += " type Inner = {{STRUCT_TY}}<'a>;";
|
code_ += " type Inner = {{STRUCT_TY}}<'a>;";
|
||||||
code_ += " #[inline]";
|
code_ += " #[inline]";
|
||||||
code_ += " fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
|
code_ += " unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
|
||||||
code_ += " Self { _tab: flatbuffers::Table { buf, loc } }";
|
code_ += " Self { _tab: flatbuffers::Table::new(buf, loc) }";
|
||||||
code_ += " }";
|
code_ += " }";
|
||||||
code_ += "}";
|
code_ += "}";
|
||||||
code_ += "";
|
code_ += "";
|
||||||
@@ -1672,7 +1675,7 @@ class RustGenerator : public BaseGenerator {
|
|||||||
|
|
||||||
code_ += " #[inline]";
|
code_ += " #[inline]";
|
||||||
code_ +=
|
code_ +=
|
||||||
" pub fn init_from_table(table: flatbuffers::Table<'a>) -> "
|
" pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> "
|
||||||
"Self {";
|
"Self {";
|
||||||
code_ += " {{STRUCT_TY}} { _tab: table }";
|
code_ += " {{STRUCT_TY}} { _tab: table }";
|
||||||
code_ += " }";
|
code_ += " }";
|
||||||
@@ -1764,16 +1767,7 @@ class RustGenerator : public BaseGenerator {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ftVectorOfInteger:
|
case ftVectorOfInteger:
|
||||||
case ftVectorOfBool: {
|
case ftVectorOfBool:
|
||||||
if (IsOneByte(type.VectorType().base_type)) {
|
|
||||||
// 1 byte stuff is viewed w/ slice instead of flatbuffer::Vector
|
|
||||||
// and thus needs to be cloned out of the slice.
|
|
||||||
code_.SetValue("EXPR", "x.to_vec()");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
code_.SetValue("EXPR", "x.into_iter().collect()");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ftVectorOfFloat:
|
case ftVectorOfFloat:
|
||||||
case ftVectorOfEnumKey: {
|
case ftVectorOfEnumKey: {
|
||||||
code_.SetValue("EXPR", "x.into_iter().collect()");
|
code_.SetValue("EXPR", "x.into_iter().collect()");
|
||||||
@@ -1840,6 +1834,9 @@ class RustGenerator : public BaseGenerator {
|
|||||||
this->GenComment(field.doc_comment);
|
this->GenComment(field.doc_comment);
|
||||||
code_ += "#[inline]";
|
code_ += "#[inline]";
|
||||||
code_ += "pub fn {{FIELD}}(&self) -> {{RETURN_TYPE}} {";
|
code_ += "pub fn {{FIELD}}(&self) -> {{RETURN_TYPE}} {";
|
||||||
|
code_ += " // Safety:";
|
||||||
|
code_ += " // Created from valid Table for this object";
|
||||||
|
code_ += " // which contains a valid value in this slot";
|
||||||
code_ += " " + GenTableAccessorFuncBody(field, "'a");
|
code_ += " " + GenTableAccessorFuncBody(field, "'a");
|
||||||
code_ += "}";
|
code_ += "}";
|
||||||
|
|
||||||
@@ -1864,16 +1861,22 @@ class RustGenerator : public BaseGenerator {
|
|||||||
code_ += "{{NESTED}}<'a> {";
|
code_ += "{{NESTED}}<'a> {";
|
||||||
code_ += " let data = self.{{FIELD}}();";
|
code_ += " let data = self.{{FIELD}}();";
|
||||||
code_ += " use flatbuffers::Follow;";
|
code_ += " use flatbuffers::Follow;";
|
||||||
|
code_ += " // Safety:";
|
||||||
|
code_ += " // Created from a valid Table for this object";
|
||||||
|
code_ += " // Which contains a valid flatbuffer in this slot";
|
||||||
code_ +=
|
code_ +=
|
||||||
" <flatbuffers::ForwardsUOffset<{{NESTED}}<'a>>>"
|
" unsafe { <flatbuffers::ForwardsUOffset<{{NESTED}}<'a>>>"
|
||||||
"::follow(data, 0)";
|
"::follow(data.bytes(), 0) }";
|
||||||
} else {
|
} else {
|
||||||
code_ += "Option<{{NESTED}}<'a>> {";
|
code_ += "Option<{{NESTED}}<'a>> {";
|
||||||
code_ += " self.{{FIELD}}().map(|data| {";
|
code_ += " self.{{FIELD}}().map(|data| {";
|
||||||
code_ += " use flatbuffers::Follow;";
|
code_ += " use flatbuffers::Follow;";
|
||||||
|
code_ += " // Safety:";
|
||||||
|
code_ += " // Created from a valid Table for this object";
|
||||||
|
code_ += " // Which contains a valid flatbuffer in this slot";
|
||||||
code_ +=
|
code_ +=
|
||||||
" <flatbuffers::ForwardsUOffset<{{NESTED}}<'a>>>"
|
" unsafe { <flatbuffers::ForwardsUOffset<{{NESTED}}<'a>>>"
|
||||||
"::follow(data, 0)";
|
"::follow(data.bytes(), 0) }";
|
||||||
code_ += " })";
|
code_ += " })";
|
||||||
}
|
}
|
||||||
code_ += "}";
|
code_ += "}";
|
||||||
@@ -1909,11 +1912,17 @@ class RustGenerator : public BaseGenerator {
|
|||||||
// as of April 10, 2020
|
// as of April 10, 2020
|
||||||
if (field.IsRequired()) {
|
if (field.IsRequired()) {
|
||||||
code_ += " let u = self.{{FIELD}}();";
|
code_ += " let u = self.{{FIELD}}();";
|
||||||
code_ += " Some({{U_ELEMENT_TABLE_TYPE}}::init_from_table(u))";
|
code_ += " // Safety:";
|
||||||
|
code_ += " // Created from a valid Table for this object";
|
||||||
|
code_ += " // Which contains a valid union in this slot";
|
||||||
|
code_ += " Some(unsafe { {{U_ELEMENT_TABLE_TYPE}}::init_from_table(u) })";
|
||||||
} else {
|
} else {
|
||||||
code_ +=
|
code_ +=" self.{{FIELD}}().map(|t| {";
|
||||||
" self.{{FIELD}}().map("
|
code_ += " // Safety:";
|
||||||
"{{U_ELEMENT_TABLE_TYPE}}::init_from_table)";
|
code_ += " // Created from a valid Table for this object";
|
||||||
|
code_ += " // Which contains a valid union in this slot";
|
||||||
|
code_ += " unsafe { {{U_ELEMENT_TABLE_TYPE}}::init_from_table(t) }";
|
||||||
|
code_ += " })";
|
||||||
}
|
}
|
||||||
code_ += " } else {";
|
code_ += " } else {";
|
||||||
code_ += " None";
|
code_ += " None";
|
||||||
@@ -2282,8 +2291,8 @@ class RustGenerator : public BaseGenerator {
|
|||||||
|
|
||||||
MapNativeTableField(
|
MapNativeTableField(
|
||||||
field,
|
field,
|
||||||
"let w: Vec<_> = x.iter().map(|s| s.as_ref()).collect();"
|
"let w: Vec<_> = x.iter().map(|s| _fbb.create_string(s)).collect();"
|
||||||
"_fbb.create_vector_of_strings(&w)");
|
"_fbb.create_vector(&w)");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case ftVectorOfTable: {
|
case ftVectorOfTable: {
|
||||||
@@ -2374,32 +2383,6 @@ class RustGenerator : public BaseGenerator {
|
|||||||
code_.SetValue("STRUCT_FN", namer_.Function(struct_def));
|
code_.SetValue("STRUCT_FN", namer_.Function(struct_def));
|
||||||
code_.SetValue("STRUCT_CONST", namer_.Constant(struct_def.name));
|
code_.SetValue("STRUCT_CONST", namer_.Constant(struct_def.name));
|
||||||
|
|
||||||
// The root datatype accessors:
|
|
||||||
code_ += "#[inline]";
|
|
||||||
code_ +=
|
|
||||||
"#[deprecated(since=\"2.0.0\", "
|
|
||||||
"note=\"Deprecated in favor of `root_as...` methods.\")]";
|
|
||||||
code_ +=
|
|
||||||
"pub fn get_root_as_{{STRUCT_FN}}<'a>(buf: &'a [u8])"
|
|
||||||
" -> {{STRUCT_TY}}<'a> {";
|
|
||||||
code_ +=
|
|
||||||
" unsafe { flatbuffers::root_unchecked::<{{STRUCT_TY}}"
|
|
||||||
"<'a>>(buf) }";
|
|
||||||
code_ += "}";
|
|
||||||
code_ += "";
|
|
||||||
|
|
||||||
code_ += "#[inline]";
|
|
||||||
code_ +=
|
|
||||||
"#[deprecated(since=\"2.0.0\", "
|
|
||||||
"note=\"Deprecated in favor of `root_as...` methods.\")]";
|
|
||||||
code_ +=
|
|
||||||
"pub fn get_size_prefixed_root_as_{{STRUCT_FN}}"
|
|
||||||
"<'a>(buf: &'a [u8]) -> {{STRUCT_TY}}<'a> {";
|
|
||||||
code_ +=
|
|
||||||
" unsafe { flatbuffers::size_prefixed_root_unchecked::<{{STRUCT_TY}}"
|
|
||||||
"<'a>>(buf) }";
|
|
||||||
code_ += "}";
|
|
||||||
code_ += "";
|
|
||||||
// Default verifier root fns.
|
// Default verifier root fns.
|
||||||
code_ += "#[inline]";
|
code_ += "#[inline]";
|
||||||
code_ += "/// Verifies that a buffer of bytes contains a `{{STRUCT_TY}}`";
|
code_ += "/// Verifies that a buffer of bytes contains a `{{STRUCT_TY}}`";
|
||||||
@@ -2641,43 +2624,25 @@ class RustGenerator : public BaseGenerator {
|
|||||||
// Follow for the value type, Follow for the reference type, Push for the
|
// Follow for the value type, Follow for the reference type, Push for the
|
||||||
// value type, and Push for the reference type.
|
// value type, and Push for the reference type.
|
||||||
code_ += "impl flatbuffers::SimpleToVerifyInSlice for {{STRUCT_TY}} {}";
|
code_ += "impl flatbuffers::SimpleToVerifyInSlice for {{STRUCT_TY}} {}";
|
||||||
code_ += "impl flatbuffers::SafeSliceAccess for {{STRUCT_TY}} {}";
|
|
||||||
code_ += "impl<'a> flatbuffers::Follow<'a> for {{STRUCT_TY}} {";
|
code_ += "impl<'a> flatbuffers::Follow<'a> for {{STRUCT_TY}} {";
|
||||||
code_ += " type Inner = &'a {{STRUCT_TY}};";
|
code_ += " type Inner = &'a {{STRUCT_TY}};";
|
||||||
code_ += " #[inline]";
|
code_ += " #[inline]";
|
||||||
code_ += " fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
|
code_ += " unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
|
||||||
code_ += " <&'a {{STRUCT_TY}}>::follow(buf, loc)";
|
code_ += " <&'a {{STRUCT_TY}}>::follow(buf, loc)";
|
||||||
code_ += " }";
|
code_ += " }";
|
||||||
code_ += "}";
|
code_ += "}";
|
||||||
code_ += "impl<'a> flatbuffers::Follow<'a> for &'a {{STRUCT_TY}} {";
|
code_ += "impl<'a> flatbuffers::Follow<'a> for &'a {{STRUCT_TY}} {";
|
||||||
code_ += " type Inner = &'a {{STRUCT_TY}};";
|
code_ += " type Inner = &'a {{STRUCT_TY}};";
|
||||||
code_ += " #[inline]";
|
code_ += " #[inline]";
|
||||||
code_ += " fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
|
code_ += " unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
|
||||||
code_ += " flatbuffers::follow_cast_ref::<{{STRUCT_TY}}>(buf, loc)";
|
code_ += " flatbuffers::follow_cast_ref::<{{STRUCT_TY}}>(buf, loc)";
|
||||||
code_ += " }";
|
code_ += " }";
|
||||||
code_ += "}";
|
code_ += "}";
|
||||||
code_ += "impl<'b> flatbuffers::Push for {{STRUCT_TY}} {";
|
code_ += "impl<'b> flatbuffers::Push for {{STRUCT_TY}} {";
|
||||||
code_ += " type Output = {{STRUCT_TY}};";
|
code_ += " type Output = {{STRUCT_TY}};";
|
||||||
code_ += " #[inline]";
|
code_ += " #[inline]";
|
||||||
code_ += " fn push(&self, dst: &mut [u8], _rest: &[u8]) {";
|
code_ += " unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {";
|
||||||
code_ += " let src = unsafe {";
|
code_ += " let src = ::core::slice::from_raw_parts(self as *const {{STRUCT_TY}} as *const u8, Self::size());";
|
||||||
code_ +=
|
|
||||||
" ::core::slice::from_raw_parts("
|
|
||||||
"self as *const {{STRUCT_TY}} as *const u8, Self::size())";
|
|
||||||
code_ += " };";
|
|
||||||
code_ += " dst.copy_from_slice(src);";
|
|
||||||
code_ += " }";
|
|
||||||
code_ += "}";
|
|
||||||
code_ += "impl<'b> flatbuffers::Push for &'b {{STRUCT_TY}} {";
|
|
||||||
code_ += " type Output = {{STRUCT_TY}};";
|
|
||||||
code_ += "";
|
|
||||||
code_ += " #[inline]";
|
|
||||||
code_ += " fn push(&self, dst: &mut [u8], _rest: &[u8]) {";
|
|
||||||
code_ += " let src = unsafe {";
|
|
||||||
code_ +=
|
|
||||||
" ::core::slice::from_raw_parts("
|
|
||||||
"*self as *const {{STRUCT_TY}} as *const u8, Self::size())";
|
|
||||||
code_ += " };";
|
|
||||||
code_ += " dst.copy_from_slice(src);";
|
code_ += " dst.copy_from_slice(src);";
|
||||||
code_ += " }";
|
code_ += " }";
|
||||||
code_ += "}";
|
code_ += "}";
|
||||||
@@ -2754,6 +2719,9 @@ class RustGenerator : public BaseGenerator {
|
|||||||
// Getter.
|
// Getter.
|
||||||
if (IsStruct(field.value.type)) {
|
if (IsStruct(field.value.type)) {
|
||||||
code_ += "pub fn {{FIELD}}(&self) -> &{{FIELD_TYPE}} {";
|
code_ += "pub fn {{FIELD}}(&self) -> &{{FIELD_TYPE}} {";
|
||||||
|
code_ += " // Safety:";
|
||||||
|
code_ += " // Created from a valid Table for this object";
|
||||||
|
code_ += " // Which contains a valid struct in this slot";
|
||||||
code_ +=
|
code_ +=
|
||||||
" unsafe {"
|
" unsafe {"
|
||||||
" &*(self.0[{{FIELD_OFFSET}}..].as_ptr() as *const"
|
" &*(self.0[{{FIELD_OFFSET}}..].as_ptr() as *const"
|
||||||
@@ -2765,20 +2733,26 @@ class RustGenerator : public BaseGenerator {
|
|||||||
code_ +=
|
code_ +=
|
||||||
"pub fn {{FIELD}}(&'a self) -> "
|
"pub fn {{FIELD}}(&'a self) -> "
|
||||||
"flatbuffers::Array<'a, {{ARRAY_ITEM}}, {{ARRAY_SIZE}}> {";
|
"flatbuffers::Array<'a, {{ARRAY_ITEM}}, {{ARRAY_SIZE}}> {";
|
||||||
code_ += " flatbuffers::Array::follow(&self.0, {{FIELD_OFFSET}})";
|
code_ += " // Safety:";
|
||||||
|
code_ += " // Created from a valid Table for this object";
|
||||||
|
code_ += " // Which contains a valid array in this slot";
|
||||||
|
code_ += " unsafe { flatbuffers::Array::follow(&self.0, {{FIELD_OFFSET}}) }";
|
||||||
} else {
|
} else {
|
||||||
code_ += "pub fn {{FIELD}}(&self) -> {{FIELD_TYPE}} {";
|
code_ += "pub fn {{FIELD}}(&self) -> {{FIELD_TYPE}} {";
|
||||||
code_ +=
|
code_ +=
|
||||||
" let mut mem = core::mem::MaybeUninit::"
|
" let mut mem = core::mem::MaybeUninit::"
|
||||||
"<{{FIELD_TYPE}}>::uninit();";
|
"<<{{FIELD_TYPE}} as EndianScalar>::Scalar>::uninit();";
|
||||||
code_ += " unsafe {";
|
code_ += " // Safety:";
|
||||||
|
code_ += " // Created from a valid Table for this object";
|
||||||
|
code_ += " // Which contains a valid value in this slot";
|
||||||
|
code_ += " EndianScalar::from_little_endian(unsafe {";
|
||||||
code_ += " core::ptr::copy_nonoverlapping(";
|
code_ += " core::ptr::copy_nonoverlapping(";
|
||||||
code_ += " self.0[{{FIELD_OFFSET}}..].as_ptr(),";
|
code_ += " self.0[{{FIELD_OFFSET}}..].as_ptr(),";
|
||||||
code_ += " mem.as_mut_ptr() as *mut u8,";
|
code_ += " mem.as_mut_ptr() as *mut u8,";
|
||||||
code_ += " core::mem::size_of::<{{FIELD_TYPE}}>(),";
|
code_ += " core::mem::size_of::<<{{FIELD_TYPE}} as EndianScalar>::Scalar>(),";
|
||||||
code_ += " );";
|
code_ += " );";
|
||||||
code_ += " mem.assume_init()";
|
code_ += " mem.assume_init()";
|
||||||
code_ += " }.from_little_endian()";
|
code_ += " })";
|
||||||
}
|
}
|
||||||
code_ += "}\n";
|
code_ += "}\n";
|
||||||
// Setter.
|
// Setter.
|
||||||
@@ -2799,13 +2773,19 @@ class RustGenerator : public BaseGenerator {
|
|||||||
code_ +=
|
code_ +=
|
||||||
"pub fn set_{{FIELD}}(&mut self, items: &{{FIELD_TYPE}}) "
|
"pub fn set_{{FIELD}}(&mut self, items: &{{FIELD_TYPE}}) "
|
||||||
"{";
|
"{";
|
||||||
|
code_ += " // Safety:";
|
||||||
|
code_ += " // Created from a valid Table for this object";
|
||||||
|
code_ += " // Which contains a valid array in this slot";
|
||||||
code_ +=
|
code_ +=
|
||||||
" flatbuffers::emplace_scalar_array(&mut self.0, "
|
" unsafe { flatbuffers::emplace_scalar_array(&mut self.0, "
|
||||||
"{{FIELD_OFFSET}}, items);";
|
"{{FIELD_OFFSET}}, items) };";
|
||||||
} else {
|
} else {
|
||||||
code_.SetValue("FIELD_SIZE",
|
code_.SetValue("FIELD_SIZE",
|
||||||
NumToString(InlineSize(field.value.type)));
|
NumToString(InlineSize(field.value.type)));
|
||||||
code_ += "pub fn set_{{FIELD}}(&mut self, x: &{{FIELD_TYPE}}) {";
|
code_ += "pub fn set_{{FIELD}}(&mut self, x: &{{FIELD_TYPE}}) {";
|
||||||
|
code_ += " // Safety:";
|
||||||
|
code_ += " // Created from a valid Table for this object";
|
||||||
|
code_ += " // Which contains a valid array in this slot";
|
||||||
code_ += " unsafe {";
|
code_ += " unsafe {";
|
||||||
code_ += " core::ptr::copy(";
|
code_ += " core::ptr::copy(";
|
||||||
code_ += " x.as_ptr() as *const u8,";
|
code_ += " x.as_ptr() as *const u8,";
|
||||||
@@ -2817,11 +2797,14 @@ class RustGenerator : public BaseGenerator {
|
|||||||
} else {
|
} else {
|
||||||
code_ += "pub fn set_{{FIELD}}(&mut self, x: {{FIELD_TYPE}}) {";
|
code_ += "pub fn set_{{FIELD}}(&mut self, x: {{FIELD_TYPE}}) {";
|
||||||
code_ += " let x_le = x.to_little_endian();";
|
code_ += " let x_le = x.to_little_endian();";
|
||||||
|
code_ += " // Safety:";
|
||||||
|
code_ += " // Created from a valid Table for this object";
|
||||||
|
code_ += " // Which contains a valid value in this slot";
|
||||||
code_ += " unsafe {";
|
code_ += " unsafe {";
|
||||||
code_ += " core::ptr::copy_nonoverlapping(";
|
code_ += " core::ptr::copy_nonoverlapping(";
|
||||||
code_ += " &x_le as *const {{FIELD_TYPE}} as *const u8,";
|
code_ += " &x_le as *const _ as *const u8,";
|
||||||
code_ += " self.0[{{FIELD_OFFSET}}..].as_mut_ptr(),";
|
code_ += " self.0[{{FIELD_OFFSET}}..].as_mut_ptr(),";
|
||||||
code_ += " core::mem::size_of::<{{FIELD_TYPE}}>(),";
|
code_ += " core::mem::size_of::<<{{FIELD_TYPE}} as EndianScalar>::Scalar>(),";
|
||||||
code_ += " );";
|
code_ += " );";
|
||||||
code_ += " }";
|
code_ += " }";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1874,7 +1874,7 @@ class SwiftGenerator : public BaseGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string ValidateFunc() {
|
std::string ValidateFunc() {
|
||||||
return "static func validateVersion() { FlatBuffersVersion_22_9_24() }";
|
return "static func validateVersion() { FlatBuffersVersion_22_10_25() }";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GenType(const Type &type,
|
std::string GenType(const Type &type,
|
||||||
|
|||||||
@@ -759,10 +759,10 @@ class TsGenerator : public BaseGenerator {
|
|||||||
import.object_name = object_name;
|
import.object_name = object_name;
|
||||||
import.bare_file_path = bare_file_path;
|
import.bare_file_path = bare_file_path;
|
||||||
import.rel_file_path = rel_file_path;
|
import.rel_file_path = rel_file_path;
|
||||||
import.import_statement =
|
import.import_statement = "import { " + symbols_expression + " } from '" +
|
||||||
"import { " + symbols_expression + " } from '" + rel_file_path + ".js';";
|
rel_file_path + ".js';";
|
||||||
import.export_statement =
|
import.export_statement = "export { " + symbols_expression + " } from '." +
|
||||||
"export { " + symbols_expression + " } from '." + bare_file_path + ".js';";
|
bare_file_path + ".js';";
|
||||||
import.dependency = &dependency;
|
import.dependency = &dependency;
|
||||||
import.dependent = &dependent;
|
import.dependent = &dependent;
|
||||||
|
|
||||||
@@ -903,7 +903,7 @@ class TsGenerator : public BaseGenerator {
|
|||||||
const auto conversion_function = GenUnionConvFuncName(enum_def);
|
const auto conversion_function = GenUnionConvFuncName(enum_def);
|
||||||
|
|
||||||
ret = "(() => {\n";
|
ret = "(() => {\n";
|
||||||
ret += " let temp = " + conversion_function + "(this." +
|
ret += " const temp = " + conversion_function + "(this." +
|
||||||
namer_.Method(field_name, "Type") + "(), " +
|
namer_.Method(field_name, "Type") + "(), " +
|
||||||
field_binded_method + ");\n";
|
field_binded_method + ");\n";
|
||||||
ret += " if(temp === null) { return null; }\n";
|
ret += " if(temp === null) { return null; }\n";
|
||||||
@@ -916,17 +916,17 @@ class TsGenerator : public BaseGenerator {
|
|||||||
const auto conversion_function = GenUnionListConvFuncName(enum_def);
|
const auto conversion_function = GenUnionListConvFuncName(enum_def);
|
||||||
|
|
||||||
ret = "(() => {\n";
|
ret = "(() => {\n";
|
||||||
ret += " let ret = [];\n";
|
ret += " const ret = [];\n";
|
||||||
ret += " for(let targetEnumIndex = 0; targetEnumIndex < this." +
|
ret += " for(let targetEnumIndex = 0; targetEnumIndex < this." +
|
||||||
namer_.Method(field_name, "TypeLength") + "()" +
|
namer_.Method(field_name, "TypeLength") + "()" +
|
||||||
"; "
|
"; "
|
||||||
"++targetEnumIndex) {\n";
|
"++targetEnumIndex) {\n";
|
||||||
ret += " let targetEnum = this." +
|
ret += " const targetEnum = this." +
|
||||||
namer_.Method(field_name, "Type") + "(targetEnumIndex);\n";
|
namer_.Method(field_name, "Type") + "(targetEnumIndex);\n";
|
||||||
ret += " if(targetEnum === null || " + enum_type +
|
ret += " if(targetEnum === null || " + enum_type +
|
||||||
"[targetEnum!] === 'NONE') { "
|
"[targetEnum!] === 'NONE') { "
|
||||||
"continue; }\n\n";
|
"continue; }\n\n";
|
||||||
ret += " let temp = " + conversion_function + "(targetEnum, " +
|
ret += " const temp = " + conversion_function + "(targetEnum, " +
|
||||||
field_binded_method + ", targetEnumIndex);\n";
|
field_binded_method + ", targetEnumIndex);\n";
|
||||||
ret += " if(temp === null) { continue; }\n";
|
ret += " if(temp === null) { continue; }\n";
|
||||||
ret += union_has_string ? " if(typeof temp === 'string') { "
|
ret += union_has_string ? " if(typeof temp === 'string') { "
|
||||||
@@ -1102,11 +1102,13 @@ class TsGenerator : public BaseGenerator {
|
|||||||
switch (vectortype.base_type) {
|
switch (vectortype.base_type) {
|
||||||
case BASE_TYPE_STRUCT: {
|
case BASE_TYPE_STRUCT: {
|
||||||
const auto &sd = *field.value.type.struct_def;
|
const auto &sd = *field.value.type.struct_def;
|
||||||
field_type += GetTypeName(sd, /*object_api=*/true);
|
const auto field_type_name =
|
||||||
;
|
GetTypeName(sd, /*object_api=*/true);
|
||||||
|
field_type += field_type_name;
|
||||||
field_type += ")[]";
|
field_type += ")[]";
|
||||||
|
|
||||||
field_val = GenBBAccess() + ".createObjList(" +
|
field_val = GenBBAccess() + ".createObjList<" + vectortypename +
|
||||||
|
", " + field_type_name + ">(" +
|
||||||
field_binded_method + ", this." +
|
field_binded_method + ", this." +
|
||||||
namer_.Method(field, "Length") + "())";
|
namer_.Method(field, "Length") + "())";
|
||||||
|
|
||||||
@@ -1128,7 +1130,7 @@ class TsGenerator : public BaseGenerator {
|
|||||||
|
|
||||||
case BASE_TYPE_STRING: {
|
case BASE_TYPE_STRING: {
|
||||||
field_type += "string)[]";
|
field_type += "string)[]";
|
||||||
field_val = GenBBAccess() + ".createScalarList(" +
|
field_val = GenBBAccess() + ".createScalarList<string>(" +
|
||||||
field_binded_method + ", this." +
|
field_binded_method + ", this." +
|
||||||
namer_.Field(field, "Length") + "())";
|
namer_.Field(field, "Length") + "())";
|
||||||
field_offset_decl =
|
field_offset_decl =
|
||||||
@@ -1162,9 +1164,9 @@ class TsGenerator : public BaseGenerator {
|
|||||||
field_type += vectortypename;
|
field_type += vectortypename;
|
||||||
}
|
}
|
||||||
field_type += ")[]";
|
field_type += ")[]";
|
||||||
field_val = GenBBAccess() + ".createScalarList(" +
|
field_val = GenBBAccess() + ".createScalarList<" +
|
||||||
field_binded_method + ", this." +
|
vectortypename + ">(" + field_binded_method +
|
||||||
namer_.Method(field, "Length") + "())";
|
", this." + namer_.Method(field, "Length") + "())";
|
||||||
|
|
||||||
field_offset_decl =
|
field_offset_decl =
|
||||||
AddImport(imports, struct_def, struct_def).name + "." +
|
AddImport(imports, struct_def, struct_def).name + "." +
|
||||||
@@ -1260,7 +1262,7 @@ class TsGenerator : public BaseGenerator {
|
|||||||
obj_api_class = "\n";
|
obj_api_class = "\n";
|
||||||
obj_api_class += "export class ";
|
obj_api_class += "export class ";
|
||||||
obj_api_class += GetTypeName(struct_def, /*object_api=*/true);
|
obj_api_class += GetTypeName(struct_def, /*object_api=*/true);
|
||||||
obj_api_class += " {\n";
|
obj_api_class += " implements flatbuffers.IGeneratedObject {\n";
|
||||||
obj_api_class += constructor_func;
|
obj_api_class += constructor_func;
|
||||||
obj_api_class += pack_func_prototype + pack_func_offset_decl +
|
obj_api_class += pack_func_prototype + pack_func_offset_decl +
|
||||||
pack_func_create_call + "\n}";
|
pack_func_create_call + "\n}";
|
||||||
@@ -1298,12 +1300,17 @@ class TsGenerator : public BaseGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const std::string object_name = GetTypeName(struct_def);
|
const std::string object_name = GetTypeName(struct_def);
|
||||||
|
const std::string object_api_name = GetTypeName(struct_def, true);
|
||||||
|
|
||||||
// Emit constructor
|
// Emit constructor
|
||||||
GenDocComment(struct_def.doc_comment, code_ptr);
|
GenDocComment(struct_def.doc_comment, code_ptr);
|
||||||
code += "export class ";
|
code += "export class ";
|
||||||
code += object_name;
|
code += object_name;
|
||||||
code += " {\n";
|
if (parser.opts.generate_object_based_api)
|
||||||
|
code += " implements flatbuffers.IUnpackableObject<" + object_api_name +
|
||||||
|
"> {\n";
|
||||||
|
else
|
||||||
|
code += " {\n";
|
||||||
code += " bb: flatbuffers.ByteBuffer|null = null;\n";
|
code += " bb: flatbuffers.ByteBuffer|null = null;\n";
|
||||||
code += " bb_pos = 0;\n";
|
code += " bb_pos = 0;\n";
|
||||||
|
|
||||||
|
|||||||
@@ -1584,7 +1584,6 @@ CheckedError Parser::ParseVectorDelimiters(uoffset_t &count, F body) {
|
|||||||
return NoError();
|
return NoError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CheckedError Parser::ParseAlignAttribute(const std::string &align_constant,
|
CheckedError Parser::ParseAlignAttribute(const std::string &align_constant,
|
||||||
size_t min_align, size_t *align) {
|
size_t min_align, size_t *align) {
|
||||||
// Use uint8_t to avoid problems with size_t==`unsigned long` on LP64.
|
// Use uint8_t to avoid problems with size_t==`unsigned long` on LP64.
|
||||||
@@ -2450,14 +2449,17 @@ CheckedError Parser::ParseEnum(const bool is_union, EnumDef **dest,
|
|||||||
EXPECT(kTokenIntegerConstant);
|
EXPECT(kTokenIntegerConstant);
|
||||||
}
|
}
|
||||||
|
|
||||||
ECHECK(evb.AcceptEnumerator());
|
|
||||||
|
|
||||||
if (opts.proto_mode && Is('[')) {
|
if (opts.proto_mode && Is('[')) {
|
||||||
NEXT();
|
NEXT();
|
||||||
// ignore attributes on enums.
|
// ignore attributes on enums.
|
||||||
while (token_ != ']') NEXT();
|
while (token_ != ']') NEXT();
|
||||||
NEXT();
|
NEXT();
|
||||||
|
} else {
|
||||||
|
// parse attributes in fbs schema
|
||||||
|
ECHECK(ParseMetaData(&ev.attributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ECHECK(evb.AcceptEnumerator());
|
||||||
}
|
}
|
||||||
if (!Is(opts.proto_mode ? ';' : ',')) break;
|
if (!Is(opts.proto_mode ? ';' : ',')) break;
|
||||||
NEXT();
|
NEXT();
|
||||||
@@ -2552,7 +2554,8 @@ bool Parser::SupportsOptionalScalars(const flatbuffers::IDLOptions &opts) {
|
|||||||
IDLOptions::kRust | IDLOptions::kSwift | IDLOptions::kLobster |
|
IDLOptions::kRust | IDLOptions::kSwift | IDLOptions::kLobster |
|
||||||
IDLOptions::kKotlin | IDLOptions::kCpp | IDLOptions::kJava |
|
IDLOptions::kKotlin | IDLOptions::kCpp | IDLOptions::kJava |
|
||||||
IDLOptions::kCSharp | IDLOptions::kTs | IDLOptions::kBinary |
|
IDLOptions::kCSharp | IDLOptions::kTs | IDLOptions::kBinary |
|
||||||
IDLOptions::kGo | IDLOptions::kPython | IDLOptions::kJson;
|
IDLOptions::kGo | IDLOptions::kPython | IDLOptions::kJson |
|
||||||
|
IDLOptions::kNim;
|
||||||
unsigned long langs = opts.lang_to_generate;
|
unsigned long langs = opts.lang_to_generate;
|
||||||
return (langs > 0 && langs < IDLOptions::kMAX) && !(langs & ~supported_langs);
|
return (langs > 0 && langs < IDLOptions::kMAX) && !(langs & ~supported_langs);
|
||||||
}
|
}
|
||||||
@@ -2563,7 +2566,7 @@ bool Parser::SupportsOptionalScalars() const {
|
|||||||
|
|
||||||
bool Parser::SupportsDefaultVectorsAndStrings() const {
|
bool Parser::SupportsDefaultVectorsAndStrings() const {
|
||||||
static FLATBUFFERS_CONSTEXPR unsigned long supported_langs =
|
static FLATBUFFERS_CONSTEXPR unsigned long supported_langs =
|
||||||
IDLOptions::kRust | IDLOptions::kSwift;
|
IDLOptions::kRust | IDLOptions::kSwift | IDLOptions::kNim;
|
||||||
return !(opts.lang_to_generate & ~supported_langs);
|
return !(opts.lang_to_generate & ~supported_langs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2571,7 +2574,7 @@ bool Parser::SupportsAdvancedUnionFeatures() const {
|
|||||||
return (opts.lang_to_generate &
|
return (opts.lang_to_generate &
|
||||||
~(IDLOptions::kCpp | IDLOptions::kTs | IDLOptions::kPhp |
|
~(IDLOptions::kCpp | IDLOptions::kTs | IDLOptions::kPhp |
|
||||||
IDLOptions::kJava | IDLOptions::kCSharp | IDLOptions::kKotlin |
|
IDLOptions::kJava | IDLOptions::kCSharp | IDLOptions::kKotlin |
|
||||||
IDLOptions::kBinary | IDLOptions::kSwift)) == 0;
|
IDLOptions::kBinary | IDLOptions::kSwift | IDLOptions::kNim)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Parser::SupportsAdvancedArrayFeatures() const {
|
bool Parser::SupportsAdvancedArrayFeatures() const {
|
||||||
@@ -3415,7 +3418,6 @@ CheckedError Parser::CheckPrivatelyLeakedFields(const Definition &def,
|
|||||||
return NoError();
|
return NoError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CheckedError Parser::DoParse(const char *source, const char **include_paths,
|
CheckedError Parser::DoParse(const char *source, const char **include_paths,
|
||||||
const char *source_filename,
|
const char *source_filename,
|
||||||
const char *include_filename) {
|
const char *include_filename) {
|
||||||
@@ -3633,6 +3635,44 @@ std::set<std::string> Parser::GetIncludedFilesRecursive(
|
|||||||
|
|
||||||
// Schema serialization functionality:
|
// Schema serialization functionality:
|
||||||
|
|
||||||
|
static flatbuffers::Offset<
|
||||||
|
flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
|
||||||
|
SerializeAttributesCommon(const SymbolTable<Value> &attributes,
|
||||||
|
FlatBufferBuilder *builder, const Parser &parser) {
|
||||||
|
std::vector<flatbuffers::Offset<reflection::KeyValue>> attrs;
|
||||||
|
for (auto kv = attributes.dict.begin(); kv != attributes.dict.end(); ++kv) {
|
||||||
|
auto it = parser.known_attributes_.find(kv->first);
|
||||||
|
FLATBUFFERS_ASSERT(it != parser.known_attributes_.end());
|
||||||
|
if (parser.opts.binary_schema_builtins || !it->second) {
|
||||||
|
auto key = builder->CreateString(kv->first);
|
||||||
|
auto val = builder->CreateString(kv->second->constant);
|
||||||
|
attrs.push_back(reflection::CreateKeyValue(*builder, key, val));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (attrs.size()) {
|
||||||
|
return builder->CreateVectorOfSortedTables(&attrs);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool DeserializeAttributesCommon(
|
||||||
|
SymbolTable<Value> &attributes, Parser &parser,
|
||||||
|
const Vector<Offset<reflection::KeyValue>> *attrs) {
|
||||||
|
if (attrs == nullptr) return true;
|
||||||
|
for (uoffset_t i = 0; i < attrs->size(); ++i) {
|
||||||
|
auto kv = attrs->Get(i);
|
||||||
|
auto value = new Value();
|
||||||
|
if (kv->value()) { value->constant = kv->value()->str(); }
|
||||||
|
if (attributes.Add(kv->key()->str(), value)) {
|
||||||
|
delete value;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
parser.known_attributes_[kv->key()->str()];
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void Parser::Serialize() {
|
void Parser::Serialize() {
|
||||||
builder_.Clear();
|
builder_.Clear();
|
||||||
AssignIndices(structs_.vec);
|
AssignIndices(structs_.vec);
|
||||||
@@ -3918,32 +3958,52 @@ bool EnumDef::Deserialize(Parser &parser, const reflection::Enum *_enum) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Offset<reflection::EnumVal> EnumVal::Serialize(FlatBufferBuilder *builder,
|
flatbuffers::Offset<
|
||||||
const Parser &parser) const {
|
flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
|
||||||
auto name__ = builder->CreateString(name);
|
EnumVal::SerializeAttributes(FlatBufferBuilder *builder,
|
||||||
auto type__ = union_type.Serialize(builder);
|
const Parser &parser) const {
|
||||||
auto docs__ = parser.opts.binary_schema_comments
|
return SerializeAttributesCommon(attributes, builder, parser);
|
||||||
? builder->CreateVectorOfStrings(doc_comment)
|
|
||||||
: 0;
|
|
||||||
return reflection::CreateEnumVal(*builder, name__, value, type__, docs__);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EnumVal::Deserialize(const Parser &parser,
|
bool EnumVal::DeserializeAttributes(
|
||||||
const reflection::EnumVal *val) {
|
Parser &parser, const Vector<Offset<reflection::KeyValue>> *attrs) {
|
||||||
|
return DeserializeAttributesCommon(attributes, parser, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
Offset<reflection::EnumVal> EnumVal::Serialize(FlatBufferBuilder *builder,
|
||||||
|
const Parser &parser) const {
|
||||||
|
const auto name__ = builder->CreateString(name);
|
||||||
|
const auto type__ = union_type.Serialize(builder);
|
||||||
|
const auto attr__ = SerializeAttributes(builder, parser);
|
||||||
|
const auto docs__ = parser.opts.binary_schema_comments
|
||||||
|
? builder->CreateVectorOfStrings(doc_comment)
|
||||||
|
: 0;
|
||||||
|
return reflection::CreateEnumVal(*builder, name__, value, type__, docs__,
|
||||||
|
attr__);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EnumVal::Deserialize(Parser &parser, const reflection::EnumVal *val) {
|
||||||
name = val->name()->str();
|
name = val->name()->str();
|
||||||
value = val->value();
|
value = val->value();
|
||||||
if (!union_type.Deserialize(parser, val->union_type())) return false;
|
if (!union_type.Deserialize(parser, val->union_type())) return false;
|
||||||
|
if (!DeserializeAttributes(parser, val->attributes())) return false;
|
||||||
DeserializeDoc(doc_comment, val->documentation());
|
DeserializeDoc(doc_comment, val->documentation());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Offset<reflection::Type> Type::Serialize(FlatBufferBuilder *builder) const {
|
Offset<reflection::Type> Type::Serialize(FlatBufferBuilder *builder) const {
|
||||||
|
size_t element_size = SizeOf(element);
|
||||||
|
if (base_type == BASE_TYPE_VECTOR && element == BASE_TYPE_STRUCT &&
|
||||||
|
struct_def->bytesize != 0) {
|
||||||
|
// struct_def->bytesize==0 means struct is table
|
||||||
|
element_size = struct_def->bytesize;
|
||||||
|
}
|
||||||
return reflection::CreateType(
|
return reflection::CreateType(
|
||||||
*builder, static_cast<reflection::BaseType>(base_type),
|
*builder, static_cast<reflection::BaseType>(base_type),
|
||||||
static_cast<reflection::BaseType>(element),
|
static_cast<reflection::BaseType>(element),
|
||||||
struct_def ? struct_def->index : (enum_def ? enum_def->index : -1),
|
struct_def ? struct_def->index : (enum_def ? enum_def->index : -1),
|
||||||
fixed_length, static_cast<uint32_t>(SizeOf(base_type)),
|
fixed_length, static_cast<uint32_t>(SizeOf(base_type)),
|
||||||
static_cast<uint32_t>(SizeOf(element)));
|
static_cast<uint32_t>(element_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Type::Deserialize(const Parser &parser, const reflection::Type *type) {
|
bool Type::Deserialize(const Parser &parser, const reflection::Type *type) {
|
||||||
@@ -3977,37 +4037,12 @@ flatbuffers::Offset<
|
|||||||
flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
|
flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
|
||||||
Definition::SerializeAttributes(FlatBufferBuilder *builder,
|
Definition::SerializeAttributes(FlatBufferBuilder *builder,
|
||||||
const Parser &parser) const {
|
const Parser &parser) const {
|
||||||
std::vector<flatbuffers::Offset<reflection::KeyValue>> attrs;
|
return SerializeAttributesCommon(attributes, builder, parser);
|
||||||
for (auto kv = attributes.dict.begin(); kv != attributes.dict.end(); ++kv) {
|
|
||||||
auto it = parser.known_attributes_.find(kv->first);
|
|
||||||
FLATBUFFERS_ASSERT(it != parser.known_attributes_.end());
|
|
||||||
if (parser.opts.binary_schema_builtins || !it->second) {
|
|
||||||
auto key = builder->CreateString(kv->first);
|
|
||||||
auto val = builder->CreateString(kv->second->constant);
|
|
||||||
attrs.push_back(reflection::CreateKeyValue(*builder, key, val));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (attrs.size()) {
|
|
||||||
return builder->CreateVectorOfSortedTables(&attrs);
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Definition::DeserializeAttributes(
|
bool Definition::DeserializeAttributes(
|
||||||
Parser &parser, const Vector<Offset<reflection::KeyValue>> *attrs) {
|
Parser &parser, const Vector<Offset<reflection::KeyValue>> *attrs) {
|
||||||
if (attrs == nullptr) return true;
|
return DeserializeAttributesCommon(attributes, parser, attrs);
|
||||||
for (uoffset_t i = 0; i < attrs->size(); ++i) {
|
|
||||||
auto kv = attrs->Get(i);
|
|
||||||
auto value = new Value();
|
|
||||||
if (kv->value()) { value->constant = kv->value()->str(); }
|
|
||||||
if (attributes.Add(kv->key()->str(), value)) {
|
|
||||||
delete value;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
parser.known_attributes_[kv->key()->str()];
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
@@ -4122,7 +4157,7 @@ std::string Parser::ConformTo(const Parser &base) {
|
|||||||
struct_def.defined_namespace->GetFullyQualifiedName(struct_def.name);
|
struct_def.defined_namespace->GetFullyQualifiedName(struct_def.name);
|
||||||
auto struct_def_base = base.LookupStruct(qualified_name);
|
auto struct_def_base = base.LookupStruct(qualified_name);
|
||||||
if (!struct_def_base) continue;
|
if (!struct_def_base) continue;
|
||||||
std::set<FieldDef*> renamed_fields;
|
std::set<FieldDef *> renamed_fields;
|
||||||
for (auto fit = struct_def.fields.vec.begin();
|
for (auto fit = struct_def.fields.vec.begin();
|
||||||
fit != struct_def.fields.vec.end(); ++fit) {
|
fit != struct_def.fields.vec.end(); ++fit) {
|
||||||
auto &field = **fit;
|
auto &field = **fit;
|
||||||
@@ -4151,15 +4186,15 @@ std::string Parser::ConformTo(const Parser &base) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//deletion of trailing fields are not allowed
|
// deletion of trailing fields are not allowed
|
||||||
for (auto fit = struct_def_base->fields.vec.begin();
|
for (auto fit = struct_def_base->fields.vec.begin();
|
||||||
fit != struct_def_base->fields.vec.end(); ++fit ) {
|
fit != struct_def_base->fields.vec.end(); ++fit) {
|
||||||
auto &field_base = **fit;
|
auto &field_base = **fit;
|
||||||
//not a renamed field
|
// not a renamed field
|
||||||
if (renamed_fields.find(&field_base) == renamed_fields.end()) {
|
if (renamed_fields.find(&field_base) == renamed_fields.end()) {
|
||||||
auto field = struct_def.fields.Lookup(field_base.name);
|
auto field = struct_def.fields.Lookup(field_base.name);
|
||||||
if (!field) {
|
if (!field) {
|
||||||
return "field deleted: " + qualified_name + "." + field_base.name;
|
return "field deleted: " + qualified_name + "." + field_base.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,11 @@
|
|||||||
FlatBuffers swift can be found in both SPM
|
FlatBuffers swift can be found in both SPM
|
||||||
|
|
||||||
`.package(url: "https://github.com/mustiikhalil/flatbuffers.git", from: "X.Y.Z"),`
|
`.package(url: "https://github.com/google/flatbuffers.git", from: "X.Y.Z"),`
|
||||||
|
|
||||||
and Cocoapods
|
and Cocoapods
|
||||||
|
|
||||||
`pod 'FlatBuffers'`
|
`pod 'FlatBuffers'`
|
||||||
|
|
||||||
### Notes
|
|
||||||
|
|
||||||
1- To report any error please use the main repository.
|
|
||||||
|
|
||||||
### Contribute
|
### Contribute
|
||||||
|
|
||||||
1- Always run `swift test --generate-linuxmain` whenever new test functions are added or removed
|
1- Always run `swift test --generate-linuxmain` whenever new test functions are added or removed
|
||||||
@@ -119,4 +119,4 @@ extension UInt64: Scalar, Verifiable {
|
|||||||
public typealias NumericValue = UInt64
|
public typealias NumericValue = UInt64
|
||||||
}
|
}
|
||||||
|
|
||||||
public func FlatBuffersVersion_22_9_24() {}
|
public func FlatBuffersVersion_22_10_25() {}
|
||||||
|
|||||||
13
tests/Abc.nim
Normal file
13
tests/Abc.nim
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#[ Abc
|
||||||
|
Automatically generated by the FlatBuffers compiler, do not modify.
|
||||||
|
Or modify. I'm a message, not a cop.
|
||||||
|
|
||||||
|
flatc version: 22.10.25
|
||||||
|
|
||||||
|
Declared by :
|
||||||
|
]#
|
||||||
|
|
||||||
|
type Abc*{.pure.} = enum
|
||||||
|
A = 0.int32,
|
||||||
|
B = 1.int32,
|
||||||
|
C = 2.int32,
|
||||||
@@ -9,7 +9,7 @@ import com.google.flatbuffers.*;
|
|||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public final class LongFloatEntry extends Table {
|
public final class LongFloatEntry extends Table {
|
||||||
public static void ValidateVersion() { Constants.FLATBUFFERS_22_9_24(); }
|
public static void ValidateVersion() { Constants.FLATBUFFERS_22_10_25(); }
|
||||||
public static LongFloatEntry getRootAsLongFloatEntry(ByteBuffer _bb) { return getRootAsLongFloatEntry(_bb, new LongFloatEntry()); }
|
public static LongFloatEntry getRootAsLongFloatEntry(ByteBuffer _bb) { return getRootAsLongFloatEntry(_bb, new LongFloatEntry()); }
|
||||||
public static LongFloatEntry getRootAsLongFloatEntry(ByteBuffer _bb, LongFloatEntry obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
|
public static LongFloatEntry getRootAsLongFloatEntry(ByteBuffer _bb, LongFloatEntry obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
|
||||||
public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); }
|
public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); }
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class LongFloatEntry : Table() {
|
|||||||
return (val_1 - val_2).sign
|
return (val_1 - val_2).sign
|
||||||
}
|
}
|
||||||
companion object {
|
companion object {
|
||||||
fun validateVersion() = Constants.FLATBUFFERS_22_9_24()
|
fun validateVersion() = Constants.FLATBUFFERS_22_10_25()
|
||||||
fun getRootAsLongFloatEntry(_bb: ByteBuffer): LongFloatEntry = getRootAsLongFloatEntry(_bb, LongFloatEntry())
|
fun getRootAsLongFloatEntry(_bb: ByteBuffer): LongFloatEntry = getRootAsLongFloatEntry(_bb, LongFloatEntry())
|
||||||
fun getRootAsLongFloatEntry(_bb: ByteBuffer, obj: LongFloatEntry): LongFloatEntry {
|
fun getRootAsLongFloatEntry(_bb: ByteBuffer, obj: LongFloatEntry): LongFloatEntry {
|
||||||
_bb.order(ByteOrder.LITTLE_ENDIAN)
|
_bb.order(ByteOrder.LITTLE_ENDIAN)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import com.google.flatbuffers.*;
|
|||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public final class LongFloatMap extends Table {
|
public final class LongFloatMap extends Table {
|
||||||
public static void ValidateVersion() { Constants.FLATBUFFERS_22_9_24(); }
|
public static void ValidateVersion() { Constants.FLATBUFFERS_22_10_25(); }
|
||||||
public static LongFloatMap getRootAsLongFloatMap(ByteBuffer _bb) { return getRootAsLongFloatMap(_bb, new LongFloatMap()); }
|
public static LongFloatMap getRootAsLongFloatMap(ByteBuffer _bb) { return getRootAsLongFloatMap(_bb, new LongFloatMap()); }
|
||||||
public static LongFloatMap getRootAsLongFloatMap(ByteBuffer _bb, LongFloatMap obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
|
public static LongFloatMap getRootAsLongFloatMap(ByteBuffer _bb, LongFloatMap obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
|
||||||
public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); }
|
public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); }
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class LongFloatMap : Table() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
companion object {
|
companion object {
|
||||||
fun validateVersion() = Constants.FLATBUFFERS_22_9_24()
|
fun validateVersion() = Constants.FLATBUFFERS_22_10_25()
|
||||||
fun getRootAsLongFloatMap(_bb: ByteBuffer): LongFloatMap = getRootAsLongFloatMap(_bb, LongFloatMap())
|
fun getRootAsLongFloatMap(_bb: ByteBuffer): LongFloatMap = getRootAsLongFloatMap(_bb, LongFloatMap())
|
||||||
fun getRootAsLongFloatMap(_bb: ByteBuffer, obj: LongFloatMap): LongFloatMap {
|
fun getRootAsLongFloatMap(_bb: ByteBuffer, obj: LongFloatMap): LongFloatMap {
|
||||||
_bb.order(ByteOrder.LITTLE_ENDIAN)
|
_bb.order(ByteOrder.LITTLE_ENDIAN)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public struct KeywordsInTable : IFlatbufferObject
|
|||||||
{
|
{
|
||||||
private Table __p;
|
private Table __p;
|
||||||
public ByteBuffer ByteBuffer { get { return __p.bb; } }
|
public ByteBuffer ByteBuffer { get { return __p.bb; } }
|
||||||
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_22_9_24(); }
|
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_22_10_25(); }
|
||||||
public static KeywordsInTable GetRootAsKeywordsInTable(ByteBuffer _bb) { return GetRootAsKeywordsInTable(_bb, new KeywordsInTable()); }
|
public static KeywordsInTable GetRootAsKeywordsInTable(ByteBuffer _bb) { return GetRootAsKeywordsInTable(_bb, new KeywordsInTable()); }
|
||||||
public static KeywordsInTable GetRootAsKeywordsInTable(ByteBuffer _bb, KeywordsInTable obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
|
public static KeywordsInTable GetRootAsKeywordsInTable(ByteBuffer _bb, KeywordsInTable obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
|
||||||
public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
|
public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
|
||||||
|
|||||||
103
tests/MoreDefaults.nim
Normal file
103
tests/MoreDefaults.nim
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
#[ MoreDefaults
|
||||||
|
Automatically generated by the FlatBuffers compiler, do not modify.
|
||||||
|
Or modify. I'm a message, not a cop.
|
||||||
|
|
||||||
|
flatc version: 22.10.25
|
||||||
|
|
||||||
|
Declared by :
|
||||||
|
]#
|
||||||
|
|
||||||
|
import Abc as Abc
|
||||||
|
import flatbuffers
|
||||||
|
|
||||||
|
type MoreDefaults* = object of FlatObj
|
||||||
|
func intsLength*(self: MoreDefaults): int =
|
||||||
|
let o = self.tab.Offset(4)
|
||||||
|
if o != 0:
|
||||||
|
return self.tab.VectorLen(o)
|
||||||
|
func ints*(self: MoreDefaults, j: int): int32 =
|
||||||
|
let o = self.tab.Offset(4)
|
||||||
|
if o != 0:
|
||||||
|
var x = self.tab.Vector(o)
|
||||||
|
x += j.uoffset * 4.uoffset
|
||||||
|
return Get[int32](self.tab, x)
|
||||||
|
func ints*(self: MoreDefaults): seq[int32] =
|
||||||
|
let len = self.intsLength
|
||||||
|
for i in countup(0, len - 1):
|
||||||
|
result.add(self.ints(i))
|
||||||
|
func floatsLength*(self: MoreDefaults): int =
|
||||||
|
let o = self.tab.Offset(6)
|
||||||
|
if o != 0:
|
||||||
|
return self.tab.VectorLen(o)
|
||||||
|
func floats*(self: MoreDefaults, j: int): float32 =
|
||||||
|
let o = self.tab.Offset(6)
|
||||||
|
if o != 0:
|
||||||
|
var x = self.tab.Vector(o)
|
||||||
|
x += j.uoffset * 4.uoffset
|
||||||
|
return Get[float32](self.tab, x)
|
||||||
|
func floats*(self: MoreDefaults): seq[float32] =
|
||||||
|
let len = self.floatsLength
|
||||||
|
for i in countup(0, len - 1):
|
||||||
|
result.add(self.floats(i))
|
||||||
|
func emptyString*(self: MoreDefaults): string =
|
||||||
|
let o = self.tab.Offset(8)
|
||||||
|
if o != 0:
|
||||||
|
return self.tab.String(self.tab.Pos + o)
|
||||||
|
return ""
|
||||||
|
func someString*(self: MoreDefaults): string =
|
||||||
|
let o = self.tab.Offset(10)
|
||||||
|
if o != 0:
|
||||||
|
return self.tab.String(self.tab.Pos + o)
|
||||||
|
return ""
|
||||||
|
func abcsLength*(self: MoreDefaults): int =
|
||||||
|
let o = self.tab.Offset(12)
|
||||||
|
if o != 0:
|
||||||
|
return self.tab.VectorLen(o)
|
||||||
|
func abcs*(self: MoreDefaults, j: int): Abc.Abc =
|
||||||
|
let o = self.tab.Offset(12)
|
||||||
|
if o != 0:
|
||||||
|
var x = self.tab.Vector(o)
|
||||||
|
x += j.uoffset * 4.uoffset
|
||||||
|
return Abc.Abc(Get[int32](self.tab, x))
|
||||||
|
func abcs*(self: MoreDefaults): seq[Abc.Abc] =
|
||||||
|
let len = self.abcsLength
|
||||||
|
for i in countup(0, len - 1):
|
||||||
|
result.add(self.abcs(i))
|
||||||
|
func boolsLength*(self: MoreDefaults): int =
|
||||||
|
let o = self.tab.Offset(14)
|
||||||
|
if o != 0:
|
||||||
|
return self.tab.VectorLen(o)
|
||||||
|
func bools*(self: MoreDefaults, j: int): bool =
|
||||||
|
let o = self.tab.Offset(14)
|
||||||
|
if o != 0:
|
||||||
|
var x = self.tab.Vector(o)
|
||||||
|
x += j.uoffset * 1.uoffset
|
||||||
|
return Get[bool](self.tab, x)
|
||||||
|
func bools*(self: MoreDefaults): seq[bool] =
|
||||||
|
let len = self.boolsLength
|
||||||
|
for i in countup(0, len - 1):
|
||||||
|
result.add(self.bools(i))
|
||||||
|
proc MoreDefaultsStart*(builder: var Builder) =
|
||||||
|
builder.StartObject(6)
|
||||||
|
proc MoreDefaultsAddints*(builder: var Builder, ints: uoffset) =
|
||||||
|
builder.PrependSlot(0, ints, default(uoffset))
|
||||||
|
proc MoreDefaultsStartintsVector*(builder: var Builder, numElems: uoffset) =
|
||||||
|
builder.StartVector(4, numElems, 4)
|
||||||
|
proc MoreDefaultsAddfloats*(builder: var Builder, floats: uoffset) =
|
||||||
|
builder.PrependSlot(1, floats, default(uoffset))
|
||||||
|
proc MoreDefaultsStartfloatsVector*(builder: var Builder, numElems: uoffset) =
|
||||||
|
builder.StartVector(4, numElems, 4)
|
||||||
|
proc MoreDefaultsAddemptyString*(builder: var Builder, emptyString: uoffset) =
|
||||||
|
builder.PrependSlot(2, emptyString, default(uoffset))
|
||||||
|
proc MoreDefaultsAddsomeString*(builder: var Builder, someString: uoffset) =
|
||||||
|
builder.PrependSlot(3, someString, default(uoffset))
|
||||||
|
proc MoreDefaultsAddabcs*(builder: var Builder, abcs: uoffset) =
|
||||||
|
builder.PrependSlot(4, abcs, default(uoffset))
|
||||||
|
proc MoreDefaultsStartabcsVector*(builder: var Builder, numElems: uoffset) =
|
||||||
|
builder.StartVector(4, numElems, 4)
|
||||||
|
proc MoreDefaultsAddbools*(builder: var Builder, bools: uoffset) =
|
||||||
|
builder.PrependSlot(5, bools, default(uoffset))
|
||||||
|
proc MoreDefaultsStartboolsVector*(builder: var Builder, numElems: uoffset) =
|
||||||
|
builder.StartVector(1, numElems, 1)
|
||||||
|
proc MoreDefaultsEnd*(builder: var Builder): uoffset =
|
||||||
|
return builder.EndObject()
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
Automatically generated by the FlatBuffers compiler, do not modify.
|
Automatically generated by the FlatBuffers compiler, do not modify.
|
||||||
Or modify. I'm a message, not a cop.
|
Or modify. I'm a message, not a cop.
|
||||||
|
|
||||||
flatc version: 22.9.24
|
flatc version: 22.10.25
|
||||||
|
|
||||||
Declared by : //monster_test.fbs
|
Declared by : //monster_test.fbs
|
||||||
Rooting type : MyGame.Example.Monster (//monster_test.fbs)
|
Rooting type : MyGame.Example.Monster (//monster_test.fbs)
|
||||||
|
|||||||
26
tests/MyGame/Example/Ability.nim
Normal file
26
tests/MyGame/Example/Ability.nim
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#[ MyGame.Example.Ability
|
||||||
|
Automatically generated by the FlatBuffers compiler, do not modify.
|
||||||
|
Or modify. I'm a message, not a cop.
|
||||||
|
|
||||||
|
flatc version: 22.10.25
|
||||||
|
|
||||||
|
Declared by :
|
||||||
|
Rooting type : MyGame.Example.Monster ()
|
||||||
|
]#
|
||||||
|
|
||||||
|
import flatbuffers
|
||||||
|
|
||||||
|
type Ability* = object of FlatObj
|
||||||
|
func id*(self: Ability): uint32 =
|
||||||
|
return Get[uint32](self.tab, self.tab.Pos + 0)
|
||||||
|
func `id=`*(self: var Ability, n: uint32): bool =
|
||||||
|
return self.tab.Mutate(self.tab.Pos + 0, n)
|
||||||
|
func distance*(self: Ability): uint32 =
|
||||||
|
return Get[uint32](self.tab, self.tab.Pos + 4)
|
||||||
|
func `distance=`*(self: var Ability, n: uint32): bool =
|
||||||
|
return self.tab.Mutate(self.tab.Pos + 4, n)
|
||||||
|
proc AbilityCreate*(self: var Builder, id: uint32, distance: uint32): uoffset =
|
||||||
|
self.Prep(4, 8)
|
||||||
|
self.Prepend(distance)
|
||||||
|
self.Prepend(id)
|
||||||
|
return self.Offset()
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
Automatically generated by the FlatBuffers compiler, do not modify.
|
Automatically generated by the FlatBuffers compiler, do not modify.
|
||||||
Or modify. I'm a message, not a cop.
|
Or modify. I'm a message, not a cop.
|
||||||
|
|
||||||
flatc version: 22.9.24
|
flatc version: 22.10.25
|
||||||
|
|
||||||
Declared by : //monster_test.fbs
|
Declared by : //monster_test.fbs
|
||||||
Rooting type : MyGame.Example.Monster (//monster_test.fbs)
|
Rooting type : MyGame.Example.Monster (//monster_test.fbs)
|
||||||
|
|||||||
15
tests/MyGame/Example/Any.nim
Normal file
15
tests/MyGame/Example/Any.nim
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#[ MyGame.Example.Any
|
||||||
|
Automatically generated by the FlatBuffers compiler, do not modify.
|
||||||
|
Or modify. I'm a message, not a cop.
|
||||||
|
|
||||||
|
flatc version: 22.10.25
|
||||||
|
|
||||||
|
Declared by :
|
||||||
|
Rooting type : MyGame.Example.Monster ()
|
||||||
|
]#
|
||||||
|
|
||||||
|
type Any*{.pure.} = enum
|
||||||
|
None = 0.uint8,
|
||||||
|
Monster = 1.uint8,
|
||||||
|
TestSimpleTableWithEnum = 2.uint8,
|
||||||
|
MyGameExample2Monster = 3.uint8,
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
Automatically generated by the FlatBuffers compiler, do not modify.
|
Automatically generated by the FlatBuffers compiler, do not modify.
|
||||||
Or modify. I'm a message, not a cop.
|
Or modify. I'm a message, not a cop.
|
||||||
|
|
||||||
flatc version: 22.9.24
|
flatc version: 22.10.25
|
||||||
|
|
||||||
Declared by : //monster_test.fbs
|
Declared by : //monster_test.fbs
|
||||||
Rooting type : MyGame.Example.Monster (//monster_test.fbs)
|
Rooting type : MyGame.Example.Monster (//monster_test.fbs)
|
||||||
|
|||||||
15
tests/MyGame/Example/AnyAmbiguousAliases.nim
Normal file
15
tests/MyGame/Example/AnyAmbiguousAliases.nim
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#[ MyGame.Example.AnyAmbiguousAliases
|
||||||
|
Automatically generated by the FlatBuffers compiler, do not modify.
|
||||||
|
Or modify. I'm a message, not a cop.
|
||||||
|
|
||||||
|
flatc version: 22.10.25
|
||||||
|
|
||||||
|
Declared by :
|
||||||
|
Rooting type : MyGame.Example.Monster ()
|
||||||
|
]#
|
||||||
|
|
||||||
|
type AnyAmbiguousAliases*{.pure.} = enum
|
||||||
|
None = 0.uint8,
|
||||||
|
M1 = 1.uint8,
|
||||||
|
M2 = 2.uint8,
|
||||||
|
M3 = 3.uint8,
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
Automatically generated by the FlatBuffers compiler, do not modify.
|
Automatically generated by the FlatBuffers compiler, do not modify.
|
||||||
Or modify. I'm a message, not a cop.
|
Or modify. I'm a message, not a cop.
|
||||||
|
|
||||||
flatc version: 22.9.24
|
flatc version: 22.10.25
|
||||||
|
|
||||||
Declared by : //monster_test.fbs
|
Declared by : //monster_test.fbs
|
||||||
Rooting type : MyGame.Example.Monster (//monster_test.fbs)
|
Rooting type : MyGame.Example.Monster (//monster_test.fbs)
|
||||||
|
|||||||
15
tests/MyGame/Example/AnyUniqueAliases.nim
Normal file
15
tests/MyGame/Example/AnyUniqueAliases.nim
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#[ MyGame.Example.AnyUniqueAliases
|
||||||
|
Automatically generated by the FlatBuffers compiler, do not modify.
|
||||||
|
Or modify. I'm a message, not a cop.
|
||||||
|
|
||||||
|
flatc version: 22.10.25
|
||||||
|
|
||||||
|
Declared by :
|
||||||
|
Rooting type : MyGame.Example.Monster ()
|
||||||
|
]#
|
||||||
|
|
||||||
|
type AnyUniqueAliases*{.pure.} = enum
|
||||||
|
None = 0.uint8,
|
||||||
|
M = 1.uint8,
|
||||||
|
Ts = 2.uint8,
|
||||||
|
M2 = 3.uint8,
|
||||||
@@ -13,7 +13,7 @@ public struct ArrayTable : IFlatbufferObject
|
|||||||
{
|
{
|
||||||
private Table __p;
|
private Table __p;
|
||||||
public ByteBuffer ByteBuffer { get { return __p.bb; } }
|
public ByteBuffer ByteBuffer { get { return __p.bb; } }
|
||||||
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_22_9_24(); }
|
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_22_10_25(); }
|
||||||
public static ArrayTable GetRootAsArrayTable(ByteBuffer _bb) { return GetRootAsArrayTable(_bb, new ArrayTable()); }
|
public static ArrayTable GetRootAsArrayTable(ByteBuffer _bb) { return GetRootAsArrayTable(_bb, new ArrayTable()); }
|
||||||
public static ArrayTable GetRootAsArrayTable(ByteBuffer _bb, ArrayTable obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
|
public static ArrayTable GetRootAsArrayTable(ByteBuffer _bb, ArrayTable obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
|
||||||
public static bool ArrayTableBufferHasIdentifier(ByteBuffer _bb) { return Table.__has_identifier(_bb, "ARRT"); }
|
public static bool ArrayTableBufferHasIdentifier(ByteBuffer _bb) { return Table.__has_identifier(_bb, "ARRT"); }
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import com.google.flatbuffers.*;
|
|||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public final class ArrayTable extends Table {
|
public final class ArrayTable extends Table {
|
||||||
public static void ValidateVersion() { Constants.FLATBUFFERS_22_9_24(); }
|
public static void ValidateVersion() { Constants.FLATBUFFERS_22_10_25(); }
|
||||||
public static ArrayTable getRootAsArrayTable(ByteBuffer _bb) { return getRootAsArrayTable(_bb, new ArrayTable()); }
|
public static ArrayTable getRootAsArrayTable(ByteBuffer _bb) { return getRootAsArrayTable(_bb, new ArrayTable()); }
|
||||||
public static ArrayTable getRootAsArrayTable(ByteBuffer _bb, ArrayTable obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
|
public static ArrayTable getRootAsArrayTable(ByteBuffer _bb, ArrayTable obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
|
||||||
public static boolean ArrayTableBufferHasIdentifier(ByteBuffer _bb) { return __has_identifier(_bb, "ARRT"); }
|
public static boolean ArrayTableBufferHasIdentifier(ByteBuffer _bb) { return __has_identifier(_bb, "ARRT"); }
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
Automatically generated by the FlatBuffers compiler, do not modify.
|
Automatically generated by the FlatBuffers compiler, do not modify.
|
||||||
Or modify. I'm a message, not a cop.
|
Or modify. I'm a message, not a cop.
|
||||||
|
|
||||||
flatc version: 22.9.24
|
flatc version: 22.10.25
|
||||||
|
|
||||||
Declared by : //monster_test.fbs
|
Declared by : //monster_test.fbs
|
||||||
Rooting type : MyGame.Example.Monster (//monster_test.fbs)
|
Rooting type : MyGame.Example.Monster (//monster_test.fbs)
|
||||||
|
|||||||
18
tests/MyGame/Example/Color.nim
Normal file
18
tests/MyGame/Example/Color.nim
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#[ MyGame.Example.Color
|
||||||
|
Automatically generated by the FlatBuffers compiler, do not modify.
|
||||||
|
Or modify. I'm a message, not a cop.
|
||||||
|
|
||||||
|
flatc version: 22.10.25
|
||||||
|
|
||||||
|
Declared by :
|
||||||
|
Rooting type : MyGame.Example.Monster ()
|
||||||
|
]#
|
||||||
|
|
||||||
|
# Composite components of Monster color.
|
||||||
|
type Color*{.pure.} = enum
|
||||||
|
Red = 1.uint8,
|
||||||
|
# \brief color Green
|
||||||
|
# Green is bit_flag with value (1u << 1)
|
||||||
|
Green = 2.uint8,
|
||||||
|
# \brief color Blue (1u << 3)
|
||||||
|
Blue = 8.uint8,
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user