Giter VIP home page Giter VIP logo

butte's Introduction

Rust-native Flatbuffers

  • Actions Status
    • Continuous Integration
    • Security audit

butte's People

Contributors

aardappel avatar caspern avatar cpcloud avatar dependabot-preview[bot] avatar jean-airoldie avatar kzvi avatar lovesegfault avatar magnet avatar mxpv avatar onurkaraman avatar reyk avatar rw avatar stackdoubleflow avatar tethyssvensson avatar tymcauley avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

butte's Issues

Implicit default values of scalars not implemented

This bug is a follow-up to #59: Flatbuffers uses implicit default values for scalars. So all integers, floats, bools, or similar have an implicit default value of 0 or false. This is currently not done by butte. This also breaks compatibility with flatc as we fail to decode messages with default scalars: the field is not present in the buffer and we don't recognize it as a default value.

I've implemented a fix in PR #63 reyk@33c0548

But it depends on PRs #60 and #52 to be fixed before I can create a PR.

Improve error handling

Right now we're using anyhow in places that we probably shouldn't be. We should be able to provide much better error messages using thiserror inside the library-ish code and using anyhow only within main.

RUSTSEC-2019-0028: Unsound `impl Follow for bool`

Unsound impl Follow for bool

Details
Package flatbuffers
Version 0.6.0
URL google/flatbuffers#5530
Date 2019-10-20
Unaffected versions < 0.4.0

The implementation of impl Follow for bool allows to reinterpret arbitrary bytes as a bool.

In Rust bool has stringent requirements for its in-memory representation. Use of this function
allows to violate these requirements and invoke undefined behaviour in safe code.

See advisory page for additional details.

Missing `Default` implementation for generated `*Args`

flatc generates Default implementations for the table args. This is especially useful with many fields or when using defaults in the schema.

For example:

table Foo {                                                                                           
  a: int;                                                                                             
  b: int;                                                                                             
  c: int = 3;                                                                                
  d: string;                                                                                          
  e: string (required);                                                                               
}                                                                                                     

flatc:

pub struct FooArgs<'a> {
    pub a: i32,
    pub b: i32,
    pub c: i32,
    pub d: Option<flatbuffers::WIPOffset<&'a  str>>,
    pub e: Option<flatbuffers::WIPOffset<&'a  str>>,
}
impl<'a> Default for FooArgs<'a> {
    #[inline]
    fn default() -> Self {
        FooArgs {
            a: 0,
            b: 0,
            c: 3,
            d: None,
            e: None, // required field
        }
    }
}

butte:

pub struct FooArgs<'a> {
    pub a: i32,
    pub b: i32,
    /// The default value for this field is __3i64__
    pub c: i32,
    pub d: Option<butte::WIPOffset<&'a str>>,
    pub e: butte::WIPOffset<&'a str>,
}

alpha release?

Hi,

I know that butte is still under heavy development but would you mind making a first alpha release for crates.io? Something like 0.0.1–alpha.1 πŸ˜…

I think it is at a point where it became usable, at least for careful experiments.

Reyk

Convert namespaces from `UpperCamelCase` to `snake_case`

Hi,

the official Style guide says that namespaces are UpperCamelCase. This doesn't work so well with Rust module names that are in snake_case so flatc converts the namespace names and butte doesn't.

namespace HelloWorld;

butte:

pub mod HelloWorld {

flatc:

pub mod hello_world {

Parser chokes on field attributes

The current parser seems unable to accept field attributes (apparently named metadata in butte-build?). I had a quick try to fix this, but I have no experience with nom 5. @cpcloud maybe you have an idea?

Here's an example of a schema failing to parse:

table HelloReply {
  message: string (required);
}

Bug with PR#25 "Use i128 to represent integers"

Hi,

the PR #25 has (exposed) a bug, for example:

table Hello {
    value: int64 = 0;
}

Now uses an i128 for the default values in the Rust code even with the type being i64:

fn add_value(&mut self, value: i64) {
    self.fbb.push_slot::<i64>(Hello::VT_VALUE, value, 0i128);
}

Compilation fails using array of flatbuffer tables

With the following definition:

table MyTable {                                                                                                                                                                                             
    entries: [Entry];                                                                                                                                                                                       
}                                                                                                                                                                                                           

I get different results with flatc and butte. The latter causes a compile-time error when I try to use it:

let entries = builder.create_vector(&[entry]);
let table = MyTable::create(&mut builder, &MyTableArgs { entries });

Error:

expected struct butte::primitives::WIPOffset, found struct butte::primitives::ForwardsUOffset

The generated code seems to be the problem (ForwardsUOffset vs. WIPOffset), flatc:

pub struct MyTableArgs<'a> {                                                                                                                                                                                
    pub entries: Option<flatbuffers::WIPOffset<flatbuffers::Vector<'a , flatbuffers::ForwardsUOffset<Entry<'a >>>>>,                                                                                        
}                                                                                                                                                                                                           

butte:

pub struct MyTableArgs<'a> {                                                                                                                                                                                
    #[allow(clippy::type_complexity)]                                                                                                                                                                       
    pub entries: Option<butte::WIPOffset<butte::Vector<'a, butte::WIPOffset<Entry<&'a [u8]>>>>>,                                                                                                            
}                                                                                                                                                                                                           

clippy warnings

DISCLAIMER: I'm using a non-default clippy configuration.

With that, I have to use the following block for the generated Rust code:

#![allow(
    clippy::unreadable_literal,
    clippy::empty_enum,
    clippy::unseparated_literal_suffix
)]
#![allow(single_use_lifetimes)]

This request is a "nice-to-have", not a real issue. But as the flatbuffers crate generates quite outdated and "dirty" rust code, it would be a nice benefit if butte could try to be as rust-2018-clean as possible. Either by adding the allow directives in the generated code or by generating it in the desired style.

  • clippy::unreadable_literal: this happens with very large default values, e.g.:

    table Hello {
        value: i64 = 1000000;
    }
    

    Clippy would expect 1_000_000. The FlatBuffers schema doesn't support this and converting the format would probably be an excessive step, but it could be a case for an [allow(clippy::unreadable_literal)] in the generated code.

  • clippy::empty_enum: this happens with the offset enums, e.g.:

    pub enum HelloOffset {}
  • clippy::unseparated_literal_suffix: this is part of the vtable, e.g.:

    pub const VT_ID: butte::VOffsetT = 4u16;
                                       ^^^^ help: add an underscore: 4_u16
  • single_use_lifetimes: This warning is a bit annoying since it generates too many false positives in perfectly valid code. So I should better fix my configuration ;-). Nevertheless, it appears in a number of places:

    impl<'a> HelloOptions<&'a [u8]> {
         ^^ this...        ^^ ...is used only here     
    ``

CI: Code Coverage / coverage (pull_request) fails

Hi,

the code coverage test has multiple issues:

  • rustfmt is required and missing in coverage.yml.
  • Incremental compilation is incompatible with -Zprofile (should add CARGO_INCREMENTAL=0).
  • Even with that fixed, the butte-examples build script still fails with errors like:
    butte_build-*.gcda: cannot merge previous GCDA file: corrupt arc tag (0xXXXXXXXX)
    (this only fails in the code coverage test and seems to be related to -Zprofile).

Reyk

Preserve doc comments

The spec supports /// doc comments:

May be written as in most C-based languages. Additionally, a triple comment (///) on a line by itself signals that a comment is documentation for whatever is declared on the line after it (table/struct/field/enum/union/element), and the comment is output in the corresponding C++ code. Multiple such lines per item are allowed.

It would be nice to preserve them in the output.

Additionally, butte fails with doc comments before fields:

Error: Parse was incomplete: not parsed: table MyTable {
    /// foo
   ...

Fixed-size arrays

flatc supports fixed-sized arrays of structs. But only for C++ output, not for Rust output πŸ‘Ž

This enhancement is a nice-to-have. But the nice thing about this is that it allows to enforce the size in the schema and not just in the code.

key: [ubyte:32];

or

key: [ubyte] (size: 32); 

Table::get of default values is not implemented and broken

butte encodes default values correctly but it doesn't handle them on the receiving side. Flatbuffers fields aren't encoded in the buffer if they match the default value. On the receiving side, a default value and the absence of it in the buffer is indicated by an offset of 0 in the vtable. butte erroneously handles the returned 0 as an offset value and returns garbage from the buffer.

Union entries with associated types

The official docs has the following example under Unions:

table PointPosition { x:uint; y:uint; }
table MarkerPosition {}
union Position {
  Start:MarkerPosition,
  Point:PointPosition,
  Finish:MarkerPosition
}

This is useful when having the same type for different actions. The workaround is to wrap MarketPosition in two tables Start and Finish.

"missing required field value" with optional value

Hi,

I'm not quite sure if this is a bug or if I'm doing something wrong. With the following definition:

table Hello {
    value: string;
}

I get a the Option and a Default implementation as expected:

pub struct HelloArgs<'a> {
    pub value: Option<butte::WIPOffset<&'a str>>,
}
impl<'a> Default for HelloArgs<'a> {
  fn default() -> Self {
    Self { value: None }
  }
}

But it now fails on runtime with the missing required field value error. I think it is related to the fact that the create() method only calls the internal add_value() method if the field is Some but the finish() step fails because Hello::VT_VALUE is not set.

        if let Some(x) = args.value {
            builder.add_value(x);
        }

...add_value() sets the Hello::VT_VALUE slot...

        self.fbb.required(o, Hello::VT_VALUE, "value");

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.