Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

provide core-only mode (i.e., no-std and no-alloc) #168

Closed
BurntSushi opened this issue Dec 12, 2024 · 1 comment · Fixed by #182
Closed

provide core-only mode (i.e., no-std and no-alloc) #168

BurntSushi opened this issue Dec 12, 2024 · 1 comment · Fixed by #182
Labels
enhancement New feature or request

Comments

@BurntSushi
Copy link
Owner

From a report on reddit:


Of course, thank you for taking the time to reply!

In an embedded context, there are lots of times where you need to work with Date/Time. For example, parsing messages that contain timestamps, scheduling events, or working directly with Time/Date providers like a GNSS (GPS) engine or NTP.

On one of the devices we create at work provides logging capabilities with time stamped entries, and we fetch time via an NTP request. We also allow the user to adjust this time to account for their timezone. This requires us to work with timestamps using (currently) Chrono, but it's not always the easiest to work with.

We also commonly work with GNSS engines which provide time in awkward formats like time since epoch, or directly as UTC, which is where a crate like yours would be great.

IOT and Low-power devices used for home automation need to work with timestamps to schedule events, by converting this into a hardware timer to trigger the event or wake-up from low power mode.

Commonly libraries that are no-std and no alloc feature gate any formatting or string output, because string is heap allocated, but with crates like heapless and defmt used everywhere in embedded it would be helpful to be able to write into fixed size buffers instead.

I understand not wanting to bump MSVR, it's always difficult to balance keeping up with the ecosystem whilst maintaining support for those on older versions. Unfortunately embedded is quickly gaining traction and features are being added in the latest version to support this, so we are usually chasing the newest rust version!

@BurntSushi BurntSushi added the enhancement New feature or request label Dec 12, 2024
@BurntSushi
Copy link
Owner Author

When I initially started building Jiff, it was my original intention to provide a core-only mode. (This is why Jiff has an alloc feature, although it cannot be disabled right now.)

One reason why I abandoned that goal was because it was much harder to devise a useful and chain-able Error type without dynamic memory allocation. But in theory, I could probably arrange it so that it just provides degraded error messages in a core-only context.

Another thing that seems to be mentioned above is time zone support. Currently, Jiff requires std to offer any kind of time zone support (whether it's by querying the system time zone or querying the time zone database). In theory, we could provide time zone support via bundling TZif data via jiff-tzdb. But things like the internal Tzif type store time zone transitions in a Vec. I suppose this is one advantage to the chrono-tz style of doing things: everything is built into statically known structures.

Another thing is that jiff::tz::db() returns a "singleton" database via a OnceLock. So we'd had to do something different there for no_std (which currently just always returns an empty time zone database).

And types like TimeZoneDatabase, and more crucially, TimeZone itself, both use an Arc internally to make cloning cheap. How to deal with that in a no-alloc context is less clear.

I'd say core-only support looks pretty challenging at this point, but not impossible.

BurntSushi added a commit that referenced this issue Dec 28, 2024
As part of working toward #168, this commit puts POSIX time zone
abbreviations inline instead of on the heap. We can generally rely on
time zone abbreviations to be short, so this is "fine."

This is obviously more annoying than just using `Box<str>`, which
explains why I didn't do it this way initially. But it seems like a
no-std no-alloc mode is a good idea, so let's put in the effort to do
this right.

We do limit abbreviation strings to 30 bytes (previously 255), but this
seems bigger than the limits used by GNU software, so it should be fine.
Still, 30 bytes is a little chunky. But a POSIX time zone is only usable
from Jiff's public API via a `TimeZone`, and in that context, it's
guarded behind an `Arc`. So we should be fine. (Although, of course,
this `Arc` will disappear in core-only mode... Oh well.)

Note that we could simply declare that POSIX time zones aren't supported
in core-only mode, but they _almost_ don't rely on allocation today. It
just requires a little more work.

Our short abbreviation strings are now represent by a simple "array
string" of fixed capacity. We define a generic array string since it
seems plausible that we'll use it again.
BurntSushi added a commit that referenced this issue Dec 28, 2024
As part of working toward #168, this commit puts POSIX time zone
abbreviations inline instead of on the heap. We can generally rely on
time zone abbreviations to be short, so this is "fine."

This is obviously more annoying than just using `Box<str>`, which
explains why I didn't do it this way initially. But it seems like a
no-std no-alloc mode is a good idea, so let's put in the effort to do
this right.

We do limit abbreviation strings to 30 bytes (previously 255), but this
seems bigger than the limits used by GNU software, so it should be fine.
Still, 30 bytes is a little chunky. But a POSIX time zone is only usable
from Jiff's public API via a `TimeZone`, and in that context, it's
guarded behind an `Arc`. So we should be fine. (Although, of course,
this `Arc` will disappear in core-only mode... Oh well.)

Note that we could simply declare that POSIX time zones aren't supported
in core-only mode, but they _almost_ don't rely on allocation today. It
just requires a little more work.

Our short abbreviation strings are now represent by a simple "array
string" of fixed capacity. We define a generic array string since it
seems plausible that we'll use it again.
BurntSushi added a commit that referenced this issue Dec 28, 2024
This removes yet another needless but harmless allocation in pursuit of
progress on #168.

In this case, returning a `&str` is part of the public API when a time
zone is a fixed offset, so we do need to store the offset as a string
somewhere. Thankfully, it's pretty small (smaller than a `Box<str>`) and
there's a predictable maximum length on the string. So it's not a big
deal to just generate the string on the stack and store it in the
`TimeZone` for this case.
BurntSushi added a commit that referenced this issue Dec 29, 2024
This removes yet another needless but harmless allocation in pursuit of
progress on #168.

In this case, returning a `&str` is part of the public API when a time
zone is a fixed offset, so we do need to store the offset as a string
somewhere. Thankfully, it's pretty small (smaller than a `Box<str>`) and
there's a predictable maximum length on the string. So it's not a big
deal to just generate the string on the stack and store it in the
`TimeZone` for this case.
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant