-
Notifications
You must be signed in to change notification settings - Fork 78
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
feat: add BorshSerializeAsync
/BorshDeserializeAsync
(WIP)
#337
base: master
Are you sure you want to change the base?
Conversation
Should the |
To support |
@DanikVitek is this doable without |
# Conflicts: # Cargo.toml
I guess, if there is no need for the traits to be dyn-compatible, then the only difficulty is making the If the MSRV bump is not an issue, then it's even easier |
Ok, no. Both |
@DanikVitek can you support your assertion that the return types will need to be pin-boxed anyway by doing a minimal example in a repo outside of this pr with the right trait (BorshSerializeAsync/BorshDeserializeAsync) signatures and msrv 1.75? I think the common convention is that you cannot bump MSRV in patch releases, but in minor version releases you're free to do so. EDIT: if so (if they need to be pin-boxed anyway), i think we'll stick with |
I think the traits should be completely separate and not extend sync counterparts and lib user should be free to only implement/derive a subset or all of them if he/she desires. I was under the impression it's the case now, maybe i'm mistaken. |
Before diving into doing derive for new traits, i'd stop and do some tests with snapshots. @DanikVitek, can you choose some subset of types, which you consider core to borsh , and make sure the async counterparts serialize/deserialize to the same snapthos that the sync interface produces in tests? You're free to modify test code, as long you double check that existing snapshots aren't touched/renamed. Ideally this should be done by pure addition (no replacements/deletions) of test code (not modifying existing tests) and just checking the new snapshots are equal to older ones. This way it would be easy to verify during review that existing serialization format, provided by stable borsh subset, hasn't changed. If the existing test code changes, it kind of needs more attention to verify the old tests still run at all. It might be somewhat tedious to cover all existing (snapshot) tests at once, but that's one of the reason the feature should be made |
It appears that all of |
@DanikVitek Amazing job! I'd like to also invite you to join @race-of-sloths |
@race-of-sloths sounds nice |
@DanikVitek Thank you for your contribution! Your pull request is now a part of the Race of Sloths! Current status: waiting for scoringWe're waiting for maintainer to score this pull request with What is the Race of SlothsRace of Sloths is a friendly competition where you can participate in challenges and compete with other open-source contributors within your normal workflow For contributors:
For maintainers:
Feel free to check our website for additional details! Bot commands
|
@dj8yfo |
@DanikVitek i believe the lint https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/async_fn_in_trait/static.ASYNC_FN_IN_TRAIT.html is just a reminder to do #[trait_variant::make(Send)]
pub trait Handler {
async fn handle(&mut self, input: &Input) -> Result<String, String>;
async fn handle2(self, input: &'static str) -> Result<String, String>;
}
struct Type {
pub field: String,
}
impl Handler for Type {
async fn handle(&mut self, input: &Input) -> Result<String, String> {
let local_var = "fsdfs sdf sdf".to_owned();
self.field.push_str(&input.field);
self.field.push_str(local_var.as_str());
Ok(self.field.clone())
}
async fn handle2(mut self, input: &'static str) -> Result<String, String> {
let local_var = "fsdfs sdf sdf".to_owned();
self.field.push_str(&input);
self.field.push_str(local_var.as_str());
Ok(self.field)
}
} and it appears to run. Not hundred % sure it's gonna work with async borsh traits, but looks like ` |
Yes. To be more precise, the async block declares an anonymous type that implements I don't completely understand the behaviour of |
|
@dj8yfo |
…. Use more readable async-generic syntax
@@ -35,6 +35,19 @@ fn check_attrs_get_cratename(input: &TokenStream) -> Result<Path, Error> { | |||
/// moved to docs of **Derive Macro** `BorshSerialize` in `borsh` crate |
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.
This should have proper docs for convenience
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.
plz clarify what you mean. these were moved to borsh to have doc-tests runnable in CI and avoid circular dev-dependency on borsh for borsh-derive.
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.
Hm.. I'll look into it, because it's a bit inconvenient to look up the actual docs
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.
external users 80% of time know nothing about borsh-derive
and just use re-exports from borsh
.
For them it's just an irrelevant implementation detail. the use borsh::BorshSerialize; #[derive(BorshSerialize)] ...
pattern kind of suggests that by itself. Probably the only reason it needs to be a crate and not a submodule is it being a proc-macro
crate.
(this is about access to doc at docs.rs)
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.
as far as access to docs from an ide is concerned ,
/// Details of [`BorshSerialize`](macro@crate::BorshSerialize) derive macro.
line of backlink could be added here
so that anyone, who has clickable links in doc-port in an ide can jump there.
.
In the case of the paragon of virtue serde
, it's not much difference there:
And it's derive macro's doc isn't rich with information either: https://docs.rs/serde/latest/serde/derive.Serialize.html
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.
actually, vscode
performs a smart rewrite of this link
/// Details of [`BorshSerialize`](macro@crate::BorshSerialize) derive macro.
but this contradicts the logic of how rustdoc
perceives this link:
So i'd rather not try to adjust to a bug of a single editor in this spot,
as the correct link here is https://docs.rs/borsh/1.5.5/borsh/derive.BorshSerialize.html (what rustdoc
generates),
vs https://docs.rs/borsh-derive/1.5.5/borsh_derive/derive.BorshSerialize.html (vscode version) .
Gates implementation of [BorshSerialize] and [BorshDeserialize] | ||
* **`derive`** - | ||
Gates derive macros of [`BorshSerialize`] and | ||
[`BorshDeserialize`] traits, as well as of [`BorshSchema`], |
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.
, as well as of [
BorshSchema]
can be removed
if IS_ASYNC { | ||
cfg_if! { | ||
if #[cfg(feature = "async")] { | ||
parsed.deserialize_with_async | ||
} else { | ||
None | ||
} | ||
} | ||
} else { | ||
parsed.deserialize_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.
this looks like it can be extracted to a method get_deser_with
, similar to internals::attributes::field::Attributes::get_bounds
if IS_ASYNC { | ||
cfg_if! { | ||
if #[cfg(feature = "async")] { | ||
parsed.serialize_with_async | ||
} else { | ||
None | ||
} | ||
} | ||
} else { | ||
parsed.serialize_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.
this looks like it can be extracted to a method get_ser_with
, similar to internals::attributes::field::Attributes::get_bounds
quote! { io::Write } | ||
}; | ||
let r#async = IS_ASYNC.then(|| Token)); | ||
let lifetime = IS_ASYNC.then(|| Lifetime::new("'async_variant", Span::call_site())); |
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.
suggest changing/shortening this to __async
in the style of #260, but this change isn't mandatory/important
all of remaining comments should be resolved + an |
The conversation started in #150.
async-generic
PR: scouten/async-generic#17This implementation should be more flexible, as it allows for different runtimes and provides traits for manual implementation in case of any uncommon runtime.