Skip to content

EmbeddedChannel: use tryAs() not forceAs() #602

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

Merged
merged 8 commits into from
Mar 5, 2019

Conversation

ianpartridge
Copy link
Contributor

This is really a question - I am wondering why EmbeddedChannel calls forceAs() instead of tryAs() when attempting to read from a [NIOAny]. As the primary usecase of EmbeddedChannel is in testing why not return nil from readInbound() (or throw) so the user can handle that in their test?

@swift-nio-bot
Copy link

Can one of the admins verify this patch?

1 similar comment
@swift-nio-bot
Copy link

Can one of the admins verify this patch?

@weissi
Copy link
Member

weissi commented Aug 31, 2018

@ianpartridge that's a good question, I don't have a strong opinion. Downside is obviously that we can then no longer distinguish between empty and wrong type. The other question is if this is SemVer major... @normanmaurer / @Lukasa ?

@normanmaurer
Copy link
Member

hmm... I think if we do this we should throw as otherwise it is impossible to tell if it was empty or not as @weissi stated. And yes I think thats a semver major

@ianpartridge
Copy link
Contributor Author

ianpartridge commented Aug 31, 2018

I agree that throwing would be best, and this is SemVer major unless we did something like:

public enum EmbeddedChannelReadInboundError: Error {
    case wrongType
}

extension EmbeddedChannel {
    public func tryReadInbound<T>() throws -> T? {
        return try readFromBuffer(buffer: &channelcore.inboundBuffer)
    }

    private func readFromBuffer<T>(buffer: inout [NIOAny]) throws -> T? {
        if buffer.isEmpty {
            return nil
        }
        guard let t = buffer.removeFirst().tryAs(type: T.self) else {
            throw EmbeddedChannelReadInboundError.wrongType
        }
        return t
    }
}

(uncompiled)

@ianpartridge
Copy link
Contributor Author

Any thoughts on what you'd like to do with this?

@Lukasa
Copy link
Contributor

Lukasa commented Sep 17, 2018

So, my inclination is that we should deprecate the old functionality and simply replace it with new, better behaviour. That allows us to defer the SemVer major function removal. Then we can use @ianpartridge's solution (though the separate internal private function is probably unnecessary).

@ianpartridge ianpartridge mentioned this pull request Nov 28, 2018
1 task
@weissi weissi added this to the 2.0.0 milestone Nov 28, 2018
@weissi weissi added the ⚠️ semver/major Breaks existing public API. label Feb 28, 2019
@weissi
Copy link
Member

weissi commented Feb 28, 2019

@ianpartridge now we could take this for NIO 2. Let's just add the throws.

@ianpartridge
Copy link
Contributor Author

🙂 Let me page all this back in...

You'd like to change the existing function?

From:
public func readInbound<T>(as type: T.Type = T.self) -> T?
To:
public func readInbound<T>(as type: T.Type = T.self) throws -> T

@weissi
Copy link
Member

weissi commented Feb 28, 2019

@ianpartridge I think throws -> T?, ie. if wrong type: throws, if empty: nil

@weissi
Copy link
Member

weissi commented Feb 28, 2019

and then we can use

XCTAssertNoThrow(XCTAssertEqual(7, try channel.readInbound(as: Int.self)))

@ianpartridge
Copy link
Contributor Author

OK, I guess make readOutbound() throwing too? I started to do this but there are a lot of test updates needed once the APIs throw. I'll try and find time to update this PR but I'm a bit limited on available time I'm afraid.

@weissi
Copy link
Member

weissi commented Mar 2, 2019

@ianpartridge I created #861 which should do all the test changes necessary, so after that, yours should just work pretty much as is

@ianpartridge
Copy link
Contributor Author

Oh wow, thanks! It looks good to me.

@weissi weissi added 🆕 semver/minor Adds new public API. and removed ⚠️ semver/major Breaks existing public API. labels Mar 4, 2019
@weissi
Copy link
Member

weissi commented Mar 4, 2019

@ianpartridge my PR is now merged, so you can rebase this one I think

@ianpartridge
Copy link
Contributor Author

Thanks, I will. What are we going to throw? Are we going to add

public enum EmbeddedChannelReadInboundError: Error {
    case wrongType
}

@weissi
Copy link
Member

weissi commented Mar 4, 2019

Thanks, I will. What are we going to throw? Are we going to add

public enum EmbeddedChannelReadInboundError: Error {
    case wrongType
}

I think we could even nest that type into EmbeddedChannel, ie.

extension EmbeddedChannel {
    public enum Error {
        case wrongType(expected: Any.Type, actual: Any.Type)
    }
}

or so? Or given that so far it's only one error and we can't extend anyway after NIO 2

extension EmbeddedChannel {
    public struct WrongTypeError {
        public init (expected: Any.Type, actual: Any.Type) {}
    }
}

@Lukasa wdyt?

@Lukasa
Copy link
Contributor

Lukasa commented Mar 4, 2019

Certainly think we should embed it. Also a struct seems like the right thing to do too.

@ianpartridge
Copy link
Contributor Author

WIP but I've pushed a commit with what I think you meant :)

@weissi
Copy link
Member

weissi commented Mar 4, 2019

@ianpartridge thanks, that looks great to me! Mind writing a test or two in EmbeddedChannelTests that test that we actually throw the right error with the right values?

@ianpartridge
Copy link
Contributor Author

I pushed a few tests - let me know if you had something else in mind.

@ianpartridge
Copy link
Contributor Author

Updated to conform WrongTypeError to Equatable, so the tests can check the contents exactly. It actually found a bug, the actual was being stored as NIOAny not the actual type.

@Lukasa
Copy link
Contributor

Lukasa commented Mar 5, 2019

@swift-nio-bot test this please

Copy link
Member

@weissi weissi left a comment

Choose a reason for hiding this comment

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

thanks very much @ianpartridge

@weissi
Copy link
Member

weissi commented Mar 5, 2019

@swift-nio-bot test this please

@weissi weissi merged commit aa03d7a into apple:master Mar 5, 2019
@ianpartridge ianpartridge deleted the embedded-forceas branch March 5, 2019 11:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🆕 semver/minor Adds new public API.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants