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

modules: Expand time module with Duration, Interval and Instant support #815

Merged
merged 2 commits into from
Oct 30, 2024

Conversation

ramon-bernardo
Copy link
Contributor

This PR significantly enhances the time module introducing...

Duration, now public:

  • Added methods for creating durations from milliseconds, microseconds, nanoseconds, and floating-point seconds.
  • Provided constants for common time units (SECOND, MILLISECOND, MICROSECOND, NANOSECOND).
  • Implemented methods to convert and manipulate durations.

Interval:

  • Introduced the Interval struct with methods for managing and resetting time intervals.
  • Added the ability to create asynchronous intervals that can be used to trigger repeated events.

Instant:

  • Introduced the Instant struct to represent specific points in time.
  • Added methods to calculate the duration between instants and to check elapsed time.

The examples provided were adapted from the Tokio Time library.

Copy link
Contributor Author

@ramon-bernardo ramon-bernardo left a comment

Choose a reason for hiding this comment

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

How could we implement Timeout<T> in Rune @udoprog? I initially tried, but due to the complexities with T, I decided to pause for now... I'll try again later...

#[rune::function]
async fn timeout(duration: Duration, future: F) -> Timeout<F>
{
    Timeout {
        inner: tokio::time::timeout(duration.inner, future).await,
    }
}
#[derive(Debug, Any)]
#[rune(item = ::time)]
pub struct Timeout<T>
{
    inner: tokio::time::Timeout<T>,
}

@ramon-bernardo
Copy link
Contributor Author

ramon-bernardo commented Aug 30, 2024

Another situation is the async tick function; I'm encountering some issues with the Future trait.

module
    .function("tick", Interval::tick)
    .build_associated::<Interval>()?;

pub async fn tick(&mut self) {
    self.inner.tick().await;
}
the trait bound 

for<'a> fn(&'a mut time::Interval) -> impl std::future::Future<Output = ()> {
    time::Interval::tick
}: rune::function::Function<_, _>

is not satisfied the trait `rune::function::Function<_, _>` is not implemented for fn item 

for<'a> fn(&'a mut time::Interval) -> impl std::future::Future<Output = ()> {
    time::Interval::tick
}

@ramon-bernardo ramon-bernardo changed the title Expand time module with Duration, Interval, and Instant support Expand time module with Duration, Interval and Instant support Aug 30, 2024
crates/rune-modules/src/time.rs Show resolved Hide resolved
crates/rune-modules/src/time.rs Outdated Show resolved Hide resolved
crates/rune-modules/src/time.rs Show resolved Hide resolved
crates/rune-modules/src/time.rs Outdated Show resolved Hide resolved
@udoprog
Copy link
Collaborator

udoprog commented Aug 30, 2024

Thank you!

I'm not sure about Timeout for now. But principally it should not be generic in Rune since all futures are of a single type Future.

For tick, you might try to use a rune-specific function which takes Mut<Self>?

@ramon-bernardo ramon-bernardo marked this pull request as ready for review August 30, 2024 21:46
Copy link
Collaborator

@udoprog udoprog left a comment

Choose a reason for hiding this comment

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

You're likely to have some clippy issues that needs to be resolved, but looks good. Thank you!

docstring,
runtime::{Mut, VmError, VmResult},
vm_panic, vm_try, Any, ContextError, Module,
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

Imports are broken up per-module in the rest of the project. It leads to cleaner diffs.

Copy link
Collaborator

Choose a reason for hiding this comment

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

The current project style would be:

use rune:{docstring, vm_panic, Any, ContextError, Module};
use rune::runtime::{Mut, VmResult};

@ramon-bernardo ramon-bernardo requested a review from udoprog August 31, 2024 17:39
Comment on lines +435 to +927
pub async fn tick(mut internal: Mut<Interval>) {
internal.inner.tick().await;
}
Copy link
Contributor Author

@ramon-bernardo ramon-bernardo Aug 31, 2024

Choose a reason for hiding this comment

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

Doc for tick will be applied? It doesn't seem right to me

@ramon-bernardo
Copy link
Contributor Author

ramon-bernardo commented Sep 2, 2024

Added methods to convert between the Duration type, std::time::Duration and tokio::time::Duration. I'm working on the http module, which necessitates handling conversions between different types.

use time::Duration;

let duration = Duration::from_secs(5);
let std_duration = duration.into_std();
let tokio_duration = duration.into_tokio();

let duration_from_str = Duration::from_str(std_duration);
let duration_from_tokio = Duration::from_tokio(tokio_duration);

@udoprog udoprog added the enhancement New feature or request label Sep 2, 2024
@udoprog
Copy link
Collaborator

udoprog commented Sep 2, 2024

So some change is needed to allow a Duration to be stored as a constant value.

We currently don't seem to support it during compilation because internally we convert it to ConstValue. This is probably not necessary for types which are only used during compilation, but is needed if they are stored in the Unit since that needs to be Sync. An alternative might be to make it possible to store constant values of external types in some other way. Since they don't need to be reference-counted, they could be implemented in a thread-safe way.

@udoprog
Copy link
Collaborator

udoprog commented Sep 19, 2024

I'd suggest you skip the constants for now until support for constructing them for custom types has been implemented so this and #819 can be merged as-is and further extended once support exists.

@udoprog udoprog changed the title Expand time module with Duration, Interval and Instant support modules: Expand time module with Duration, Interval and Instant support Oct 8, 2024
@ramon-bernardo
Copy link
Contributor Author

@udoprog ready for review! 😀

Copy link
Collaborator

@udoprog udoprog left a comment

Choose a reason for hiding this comment

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

Same here, please remove commented out code and maintain in a separate branch instead if you want to keep it around for the future.

@udoprog udoprog force-pushed the time-module-expand branch from 4ec1c7c to 15abfa7 Compare October 30, 2024 16:26
@udoprog
Copy link
Collaborator

udoprog commented Oct 30, 2024

I used this as basis for #861, since Duration uses u64 and it's used to represent the full span of a Duration like with Duration::MAX. This made it really awkward and even impractical to interchangeably use the type for boundary values. Or, values which overflows i64.

I also added methods (like as_secs and more conversion methods) which were used in upstream test cases so we can adopt them more closely.

@udoprog udoprog merged commit 6aa05a6 into rune-rs:main Oct 30, 2024
24 checks passed
@ramon-bernardo ramon-bernardo deleted the time-module-expand branch October 30, 2024 19:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants