-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rust full reflection #8102
base: master
Are you sure you want to change the base?
Rust full reflection #8102
Conversation
3ea581d
to
7e5b92b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bunch of small things. Feel free to ignore nits if they don't seem worthwhile.
Great work overall!
0ee84d1
to
6868cb3
Compare
@candysonya @dextero We are using flatbuffers at work and I have a small patch that allows us to have zero-allocation of flatbuffer messages. I noticed that this change makes all the &'static str into String. Is this strictly necessary? Could it be Cow<'static, str>? |
Thanks for pointing it out! I've just updated the change with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for making the changes to Cow<'static, str>
. This is an awesome patch set and I'm really excited to have reflection! My comments are a few cases where you used .to_string()
but I believe that .into()
should work instead to make the value into a Cow
and not a String
. I could be wrong though and in that case feel free to ignore my comments
73bd124
to
913d257
Compare
Thanks so much for spotting that! |
c9465ba
to
88b2f0d
Compare
88b2f0d
to
f2f7f93
Compare
cc95976
to
358d6e5
Compare
This pull request is stale because it has been open 6 months with no activity. Please comment or label |
I do care about this feature. I may pick it up if @candysonya is unavailable. |
not-stale |
Hi @brt-adam-snaider , yes please feel free to pick it up. Do you already have a plan? |
Hi @brt-adam-snaider , I'm considering picking it up. Before that, may I know if you're already working on this? |
I haven't picked it up yet. Have at it :) |
7d2ea1f
to
6ed63ee
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thank you for following through on this!
We'll need an owner approval, I can't grant one unfortunately.
ad5edac
to
d3f36c9
Compare
Some CI issues with Rust. Can you take a look? It should auto run now next time you push to the PR. |
f3b65ea
to
ceb2218
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left a few nits, mostly about how some errors could be avoided by reorganizing the code a bit. LGTM overall, great work!
pub struct SafeBuffer<'a> { | ||
buf: &'a [u8], | ||
schema: &'a Schema<'a>, | ||
buf_loc_to_obj_idx: RwLock<HashMap<usize, i32>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need the RwLock
here? IIUC:
- the hashmap is created once in
SafeBuffer::new
and then never modified again, - the buffer the map refers to never changes either (we only have an
&
reference to it)
This makes me think we could use a plain HashMap<usize, i32>
here instead, and remove the RwLockPoisonError
.
unsafe { get_any_root(self.buf) } | ||
} | ||
|
||
/// Gets all the fields the [table] has. Returns error if the [table] doesn't match the buffer. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: the "table must match the buffer" constraint sounds like something that would be awesome to check automatically rather than having the user ensure it.
Would it be possible to have something like SafeTable
(stub name), that keeps a reference to the buffer it refers to? This could give us usage like
let buffer: SafeBuffer = SafeBuffer::new(&buf, *schema)?;
let root: SafeTable = buffer.get_root();
root.get_all_fields(); // always correct because SafeBuffer only accesses the matching buffer
And there's even a chance we could get rid of InvalidTableOrStruct
error!
} | ||
} | ||
|
||
/// Returns the value of any table field as a string, regardless of what type it is. Returns empty string if the field is not set. Returns error if |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: if this is public API, it would be nice to point out that the value gets stringified and not reinterpreted as a string, so for example an int (1234
) becomes "1234"
and not "\x01\x02\x03\x04"
(+/- endianness)
assert!(value.is_err()); | ||
assert_eq!( | ||
value.unwrap_err().to_string(), | ||
"Table or Struct doesn't belong to the buffer" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: we're using thiserror
so we could look for a specific variant of the error enum, to not have to worry about the string wording changing:
assert_eq!(matches!(value.unwrap_err(), FlatbufferError::InvalidTableOrStruct))
#[error("RwLock read/write error: {0}")] | ||
RwLockPoisonError(String), | ||
#[error("Table or Struct doesn't belong to the buffer")] | ||
InvalidTableOrStruct(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: if we don't need any data inside, we can skip the ()
and make it just InvalidTableOrStruct,
here.
It verifies buffer against schema during construction and provides all the unsafe getters in lib.rs in a safe way
0b5d56c
to
2986c39
Compare
(My teammate dextero has kindly helped to review the PR and left a lot of insightful comments. Unfortunately they are not a member of the community and they cannot approve it. Currently all the comments have been resolved and it would be highly appreciated if it could be reviewed by the community because the reflection feature in Rust is a blocker for our team to use Flatbuffers!)
Compared to the C++ implementation of the reflection feature,
It includes:
It doesn't include:
VectorOfAny
(Vector without element type specified)TODOs on C++ side are retained.