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

WIP: split Client into UnauthenticatedClient and Client #84

Merged
merged 9 commits into from
Aug 30, 2018

Conversation

dario23
Copy link

@dario23 dario23 commented Aug 11, 2018

a first attempt at the split between the unauthenticated (but connected) and the logged in state on the type level, as discussed in the comments of issue #80 . the only way to get a (logged in) Client instance is through successful calls to the login/authenticate methods. implementation-wise there's now a third type, InnerClient, which contains all lower-level functionality used by both UnauthenticatedClient and Client (to avoid duplicating the code or having weird cross-references between the Client and UnauthenticatedClient types.

as i'm mostly looking for feedback on the general direction of how i implemented the idea, there's not enough docs and i haven't ran rustfmt or cargo test yet etc. i'm especially hoping for feedback on

  • do we want connect/secure_connect to stay in the Client type (but return an UnauthenticatedClient), so people can continue to write Client::connect(..), or is it better to make the API break explicit here, as you have to deal with the return value of connect (the UnauthenticatedClient) differently now (i.e. don't provide a false sense of API continuity)?
  • perhaps we might even want to re-add wrappers for the lower-level functions in InnerClient to the Client type, so we could reverse the changes to the (non-involved) IdleHandle. for now i only added wrappers for those that were marked pub.

i'm always happy to change things and re-submit. also i wasn't sure whether UnauthenticatedClient/Client or e.g. Client/AuthenticatedClient is the better naming; if people have thoughts on that i'm happy to hear those, too (in this first attempt i opted for the former, as this keeps more of the interface on the existing Client type).

src/client.rs Outdated
match self.inner.run_command(&format!("AUTHENTICATE {}", auth_type)) {
Ok(_) => self.do_auth_handshake(authenticator),
Err(e) => Err((e, self)),
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Given the repetition of this, you may want to add a simple macro for it.

@jonhoo
Copy link
Collaborator

jonhoo commented Aug 21, 2018

I think this looks like a good approach! I'd suggest the following for naming/method placement:

  • s/InnerClient/Connection/
  • s/Client/Session/
  • s/UnauthenticatedClient/Client/
  • Add a free-standing connect method that returns a Client.

We could go even further and rename UnauthenticatedClient to Builder, where the build method is essentially login, but that might be too un-idiomatic.

The nicest way to work around all the .inner. things that have to be added is probably to add impl Deref and impl DerefMut for Session (and Client) with Target = Connection.

src/client.rs Outdated
@@ -327,13 +359,14 @@ impl<T: Read + Write> UnauthenticatedClient<T> {
mut self,
username: &str,
password: &str
) -> ::std::result::Result<Client<T>, (Error, UnauthenticatedClient<T>)> {
) -> ::std::result::Result<Session<T>, (Error, Client<T>)> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Probably make Client<T> here just Self?

@dario23
Copy link
Author

dario23 commented Aug 29, 2018

@jonhoo changed the naming of the various structs, implemented your suggestions on .inner, i.e. the Deref instances, and changed the tests accordingly, so they should now all pass as well.

depending on your preference i can squash some of the commits into one to avoid e.g. one iteration back and forth of adding .inner everywhere just to remove them again; or otherwise just leave all the commits like they are, to more accurately reflect the history/discussion here.

Copy link
Collaborator

@jonhoo jonhoo left a comment

Choose a reason for hiding this comment

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

I'm happy for you to leave the commits separate -- history is nice. Other than that, this change looks quite good! It requires a major version bump, but sadly I can't make a release due to #69 :/

The remaining things as far as I can tell are to add documentation for Session and Client. It'd also be nice to add a rust,no_run doctest example to connect and secure_connect (even though I know the original methods didn't have one). I also have a somewhat silly request that you can ignore if you don't think it's worth it: could you move the

impl <T: Read + Write> Connection<T> {

block where you have fn run_command_and_check_ok and such down to where those methods were previously defined in the file? It'll make the diff much smaller and easier to review. I think all that should be needed is to cut-paste that entire block down around line 713.

Thanks for all the great work!

@jonhoo
Copy link
Collaborator

jonhoo commented Aug 29, 2018

Re 515d574: No, sadly not. There's the #[doc] attribute for including an external file, but you can't just straight include a Rust example file that way sadly :/

src/client.rs Outdated
username: &str,
password: &str
) -> ::std::result::Result<Session<T>, (Error, Client<T>)> {
// note that we need the explicit match blocks here for two reasons:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should this comment now go away? Or perhaps be included in the macro?

Copy link
Author

Choose a reason for hiding this comment

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

ah, yes.. next commit (also including the comments from above) soon-ish :-)

dario23 added a commit to dario23/rust-imap that referenced this pull request Aug 30, 2018
@dario23
Copy link
Author

dario23 commented Aug 30, 2018

docs (including moving the comment to the macro definition) and some examples added.

I also have a somewhat silly request that you can ignore if you don't think it's worth it

i've been on both sides of very similar requests before, so happily included this one as well :-)

@coveralls
Copy link

coveralls commented Aug 30, 2018

Coverage Status

Coverage increased (+1.5%) to 71.501% when pulling b7927aa on dario23:inner_client into 61ffb00 on mattnenterprise:master.

@jonhoo
Copy link
Collaborator

jonhoo commented Aug 30, 2018

Great, almost there! I think the comment still needs to be removed from login, but apart from that this PR is now basically mergeable :D

I'll merge once that's fixed, though @mattnenterprise will need to do a (major) release. Hopefully he'll also fix #69 when he's at it.

@dario23
Copy link
Author

dario23 commented Aug 30, 2018

I think the comment still needs to be removed from login

ah, right. pushed.

@jonhoo jonhoo merged commit 9efd256 into mattnenterprise:master Aug 30, 2018
@jonhoo
Copy link
Collaborator

jonhoo commented Aug 30, 2018

Thank you!

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.

3 participants