-
Notifications
You must be signed in to change notification settings - Fork 191
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
Timestamp::from_rfc4122
panics when using timestamp before unix epoch
#680
Comments
Thanks for the report @zheland. I think we've got two options here:
Do either of those options appeal to you more than the other? |
// draft example, I have not checked the implementation in detail
pub const UUID_TICKS_BETWEEN_EPOCHS: u64 = 0x01B2_1DD2_1381_4000;
pub const UUID_SECS_BETWEEN_EPOCHS: u64 = UUID_TICKS_BETWEEN_EPOCHS / 10_000_000;
const fn unix_to_rfc4122_ticks(seconds: u64, nanos: u32) -> u64 {
seconds
.wrapping_add(UUID_SECS_BETWEEN_EPOCHS)
.wrapping_mul(10_000_000)
.wrapping_add(nanos as u64 / 100)
}
const fn rfc4122_to_unix(ticks: u64) -> (u64, u32) {
(
(ticks / 10_000_000).wrapping_sub(UUID_SECS_BETWEEN_EPOCHS),
(ticks % 10_000_000) as u32 * 100,
)
}
#[test]
fn any_rfc4122_can_be_mapped_to_the_corresponding_unixtime_and_back() {
for (rfc4122, unix) in [
(u64::MAX, (0x0000_01AA_A6D6_0F4A, 955_161_500)),
(u64::MAX / 2 + 1, (0x0000_00D3_E741_3965, 477_580_800)),
(UUID_TICKS_BETWEEN_EPOCHS, (0, 0)),
(UUID_TICKS_BETWEEN_EPOCHS - 1, (u64::MAX, 999_999_900)),
(10_000_000, (0xFFFF_FFFD_27AC_6381, 0)),
(1, (0xFFFF_FFFD_27AC_6380, 100)),
(0, (0xFFFF_FFFD_27AC_6380, 0)),
] {
assert_eq!(rfc4122_to_unix(rfc4122), unix);
assert_eq!(unix_to_rfc4122_ticks(unix.0, unix.1), rfc4122);
}
}
#[test]
fn not_any_unixtime_can_be_mapped_to_the_corresponding_rfc4122() {
assert_eq!(unix_to_rfc4122_ticks(0, 0), UUID_TICKS_BETWEEN_EPOCHS);
assert_eq!(unix_to_rfc4122_ticks(0, 99), UUID_TICKS_BETWEEN_EPOCHS);
assert_eq!(
unix_to_rfc4122_ticks(0xFE00_0000_0000_0000, 0),
UUID_TICKS_BETWEEN_EPOCHS
);
} |
I’m also more inclined to a non-panicking variant here. For anybody that’s concerned about quietly changing behaviour through wrapping or truncation we can offer a I do like that the wrapping variant gives you a more uniquely useful timestamp. I’d be happy with an implementation that did that. It might also be worth checking the current draft spec that introduces v6-v8 and see if it recommends any behaviour converting RRC4122 timestamps to Unix time. |
Thanks @zheland 👍 I've opened #691 that addresses this by explicitly wrapping, basically as you've suggested here. All we're guaranteeing is that those methods won't panic, not that they'll wrap to any particular value, so I've reflected that in the test by only ensuring overflowing inputs don't panic. |
Timestamp::from_rfc4122
method panics withattempt to subtract with overflow
error when passing ticks value less thanUUID_TICKS_BETWEEN_EPOCHS
.I'm not sure that the intentional use of a UUID with the wrong timestamp can be considered acceptable by the standard. But even if this is considered unacceptable, a
# Panics
section describing that theTimestamp::from_rfc4122
method panics at certain values would be useful in method description.The UUID crate allowed these values up to and including version
1.1.2
. In UUIDv1.1.2
the timestamp stored RFC4122 ticks. After UUIDv1.2.1
Timestamp started to use unix time instead.Code from the UUID crate for reference:
uuid/src/timestamp.rs
Lines 25 to 27 in 6188ecf
uuid/src/timestamp.rs
Lines 75 to 89 in 6188ecf
uuid/src/timestamp.rs
Lines 133 to 138 in 6188ecf
The text was updated successfully, but these errors were encountered: