Skip to content
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

Hide Value from user and use serde instead #19

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

oberblastmeister
Copy link
Contributor

In your thoughts that you posted I saw that you wanted a strongly typed api and to hide Value from the user. I have implemented that using rmp_serde and the with_serde feature flag of rmpv. This allows send_msg to send anything with args that implement Serialize opening up possibilities for a strongly typed api because using structs as args will also work. This way call and call_function can both take a wide range of values also. The base of this pr is implementing Serialize and Deserialize for RpcMessage. Before you were manually serializing and deserializing into RpcMessage. Instead I have implemented the serde traits which is much easier and fits into the serde data model. Eventually I think that we don't need Value at all and can just rely on serde. This pr can open up very cool possibilities like having custom structs for common things like CompleteItems and QfListItems.

Licensing: The code contributed to nvim-rs is licensed under the MIT or
Apache license as given in the project root directory.

@KillTheMule
Copy link
Owner

Hey sorry for leaving this open so long, I have a hard time finding time for this project. I think I can work at it again real soon, but first I'll need to do chores I guess (CI...), so it might still need some time. Especially seeing this is somewhat complicated for me :)

I'm a bit hesitating anyways, since it adds serde as a dependency, and I'm not yet sure if that's really pulling it's weight. But that strongly typed API and custom structs really are enticing!

@oberblastmeister
Copy link
Contributor Author

Its okay, I was working on a larger pr after I submitted this one by I lost interest. However, I do think it is very nice because then all functions can take a serde trait bound allowing for very expressive calling of functions.

@smolck smolck mentioned this pull request Oct 6, 2021
4 tasks
@KillTheMule
Copy link
Owner

So I'll be putting in some inline questions for @smolck who wants to take over here.

@@ -96,17 +103,31 @@ where
(req, fut)
}

async fn send_msg(
/// Will panic if args is serialized into something that is not an array
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does that happen? How can the caller ensure this doesn't happen? Could we statically guarantee that somehow?

) -> Result<oneshot::Receiver<ResponseResult>, Box<EncodeError>> {
let msgid = self.msgid_counter.fetch_add(1, Ordering::SeqCst);

fn get_args<T: Serialize + fmt::Debug>(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this inlined for a specific reason? I'd prefer if it weren't, unless I'm missing something.

@@ -119,10 +140,10 @@ where
Ok(receiver)
}

pub async fn call(
pub async fn call<T: Serialize + fmt::Debug>(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you using fmt::Debug instead of simply Debug here?


/// Pack the given arguments into a `Vec<Value>`, suitable for using it for a
/// [`call`](crate::neovim::Neovim::call) to neovim.
#[macro_export]
macro_rules! call_args {
() => (Vec::new());
() => {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this one for? If we need an empty Vec<Value> I think type inference should usually figure that out when just using vec![], right?

self
.call("nvim_call_function", call_args![fname, args])
.call("nvim_call_function", Args(fname, args))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any blanket impl's we could take advantage of here? Maybe we can just use (fname, args)? Otoh, this might just be clearer to read.

@@ -265,13 +365,13 @@ impl IntoVal<Value> for Vec<(Value, Value)> {
}
}

#[cfg(all(test, feature = "use_tokio"))]
// #[cfg(all(test, feature = "use_tokio"))]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's up with this? One can't use #[tokio::test] if the feature isn't enabled. We're not introducing a general dependency on tokio here, do we?


/// Syncronously decode the content of a reader into an rpc message. Tries to
/// give detailed errors if something went wrong.
fn decode_buffer_other<R: Read>(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this just kept as a comparison? Doesn't serve a purpose in the long run, right?

@@ -66,12 +168,24 @@ pub async fn decode<R: AsyncRead + Send + Unpin + 'static>(
*rest = rest.split_off(pos as usize); // TODO: more efficiency
return Ok(msg);
}

Err(DecodeError::BufferError(e))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this variant still needed?

@kkharji
Copy link

kkharji commented Apr 27, 2022

Maybe it would be far simpler to abstract Value to impl Into<Value>. If Value is provided it will be no-op anyways.

@KillTheMule
Copy link
Owner

That might just be feasible as well :)

@kkharji
Copy link

kkharji commented Apr 27, 2022

That might just be feasible as well :)

So I tried to manually do it then realized the code is generated, in generated code, I have gotten away with code_data: code_data.into() but for the rest I couldn't understand how to do it with the template

@KillTheMule
Copy link
Owner

Not all is generated, have a look at https://github.com/KillTheMule/nvim-rs/blob/master/src/neovim_api_manual.rs. If we figure out something good, changing the generating script can follow.

@micwoj92
Copy link

This branch has conflicts that must be resolved

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants