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

Add nanoseconds without dots #251

Merged
merged 7 commits into from
Jun 17, 2018
Merged

Conversation

emschwartz
Copy link
Contributor

@emschwartz emschwartz commented Jun 8, 2018

Resolves #250

@quodlibetor
Copy link
Contributor

Looking great!

Regarding your questions:

  • Yeah, I think we should duplicate the nanosecond parse tests, all of them. You can verify that you are only finding nanoseconds without dots by doing something like:

    check!(".400", [fix!(Nanosecond3NoDot)]; INVALID);  // probably not actually INVALID
    check!("400", [fix!(Nanosecond3NoDot)]; nanosecond: 400_000_000);

    Does that make sense?

  • Only other place to update is the strftime docs and the CHANGELOG.md

@quodlibetor
Copy link
Contributor

I took a little time to look at it, and modifying the beginning of fn.parse to include a print:

    for item in items {
        println!("s: {:?} item: {:?} parsed: {:?} ", s, item, parsed);
        match item {

results in this error:

s: "421950803547" item: Fixed(Nanosecond9NoDot)
parsed: Parsed { year: None, year_div_100: None, year_mod_100: None, isoyear: None, isoyear_div_100: None, isoyear_mod_100: None, month: None, week_from_sun: None, week_from_mon: None, isoweek: None, weekday: None, ordinal: None, day: None, hour_div_12: None, hour_mod_12: None, minute: None, second: None, nanosecond: None, timestamp: None, offset: None, _dummy: () }

s: "" item: Numeric(Second, None)
parsed: Parsed { year: None, year_div_100: None, year_mod_100: None, isoyear: None, isoyear_div_100: None, isoyear_mod_100: None, month: None, week_from_sun: None, week_from_mon: None, isoweek: None, weekday: None, ordinal: None, day: None, hour_div_12: None, hour_mod_12: None, minute: None, second: None, nanosecond: Some(421950803), timestamp: None, offset: None, _dummy: () }

thread 'format::parse::test_parse' panicked at 'assertion failed: `(left == right)`
  left: `Err(ParseError(TooShort))`,

which strongly suggests that Nanosecond9NoDot is not correctly stopping parsing after the first 9 digits (since the nanosecond field is correct), but that the surrounding parse code is still consuming the entire str.

@emschwartz
Copy link
Contributor Author

Good catch. It was an issue with using the try_consume macro with a slice of the string. try_consume updates s in place, but if you pass a slice it forgets about the whole rest of the string

check!("42195", [fix!(Nanosecond9NoDot)]; nanosecond: 421_950_000);
check!("421950803", [fix!(Nanosecond9NoDot)]; nanosecond: 421_950_803);
check!("421950803547", [fix!(Nanosecond9NoDot)]; nanosecond: 421_950_803);
// check!("421950803547", [fix!(Nanosecond9NoDot), num!(Second)]; nanosecond: 421_950_803, second: 54); // don't skip digits that come after the 9
Copy link
Contributor

Choose a reason for hiding this comment

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

did you want to uncomment this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I'm fixing the test. I'll add another commit to the PR tomorrow

Copy link
Contributor

@quodlibetor quodlibetor left a comment

Choose a reason for hiding this comment

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

Still looking good, there are two new changes:

  • You're going to need to either rebase or merge in master, and you'll probably get conflicts in the changelog
  • Could you move your new variants into the InternalInternal struct, the equivalent of this commit for your changes? It didn't exist when you started work, but I think that, sadly, it's necessary for strict semver compat.

@emschwartz
Copy link
Contributor Author

Yeah, I'll make those changes tomorrow.

Would you prefer me to squash all the commits into one or leave them as they are?

@quodlibetor
Copy link
Contributor

The commits are nicely separated as is, no need to squash. I would also appreciate the refactoring to use InternalInternal to be its own commit, I hope to revert it with the next breaking change.

Speaking of it, though, if you are going to be editing your test commit and you use git from the command line I have a very new project that I'm looking for beta testers/bug reporters/contributors on that is supposed to make editing old commits a bit nicer.

@emschwartz
Copy link
Contributor Author

Could you move your new variants into the InternalInternal struct, the equivalent of this commit for your changes? It didn't exist when you started work, but I think that, sadly, it's necessary for strict semver compat.

I'm not sure I understand that. Is the idea to make it so this feature can't be accessed by the user? What is the semver issue (it's a non-breaking change)?

@quodlibetor
Copy link
Contributor

Adding new variants to a public enum is a major breaking change. The idea isn't to prevent usage of the feature, it's to require that the only usage of the feature is through the parse method, specifically so that we don't break semver.

The hack used by the ecosystem to mark enums as open is to have a #[doc(hidden)] __DoNotMatchAgainstMe variant and to include in the docs for an enum that additions to it are expected. However, chrono was created before that convention existed, and so it created the separation of internal and external enums. The internal enum is not public, and so it can be expanded without trouble. The external enum, though, is public and so technically someone could be doing an exhaustive match against the whole thing.

For most libraries I think that just having bad docs would mean that you can just fix them and improve life, but chrono is one of the most depended-on crates in the ecosystem and so if any crate is going to have someone doing crazy things against massive enums then chrono might be it.

@quodlibetor
Copy link
Contributor

specifically, the only things that you should need to change should be to move your variants to the InternalInternal enum and to change your uses of fix! to internal_fix!, all tests (in particular tests that verify parse) should continue to work without any other changes.

@emschwartz
Copy link
Contributor Author

emschwartz commented Jun 12, 2018

Gotcha. Thanks for the explanation. Should it be InternalInternal or InternalFixed?

(Never mind, think I got it)

To avoid adding new variants to the public enum (see chronotope#251 (comment))
@emschwartz
Copy link
Contributor Author

Made the change. Ready for re-review

@emschwartz emschwartz changed the title [WIP] Add nanoseconds without dots Add nanoseconds without dots Jun 12, 2018
@quodlibetor
Copy link
Contributor

LGTM, I'm going to do one more review pass this evening, I don't recall any other possible concerns so hopefully I'll get this published tonight.

@emschwartz
Copy link
Contributor Author

Sounds good. Thanks for the help!

There is some specific behavior around writing out truncated nanos that we want
to be sure to preserve.
@quodlibetor quodlibetor merged commit 7baafaf into chronotope:master Jun 17, 2018
emschwartz added a commit to interledger/interledger-rs that referenced this pull request Jun 28, 2018
emschwartz added a commit to interledger/interledger-rs that referenced this pull request Jun 28, 2018
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.

None yet

2 participants