Skip to content

Redesign of time scale and frame transformation traits #237

@helgee

Description

@helgee

It is currently not possible to provide transformations from "builtin" time scales and reference frames to user-defined ones because of the orphan rule.

// This will not compile because both `ToScale` and `Tai` are owned by a foreign crate
impl ToScale<MyScale> for Tai {
    fn offset(&self, scale: Tt, _dt: TimeDelta) -> TimeDelta {
        ...
    }
}

--

Here's a small POC for an alternative implementation which implements the trait on a third struct, an offset provider, instead of the Time struct (take 1) or the time scale struct (take 2) directly. That way a third-party crate can own an alternative provider struct implementing OffsetProvider and the builtin types are only type parameters which do not trigger the orphan rule.

trait TimeScale {}
#[derive(Copy,Clone,Debug)]
struct Tai;
#[derive(Copy,Clone,Debug)]
struct Tt;

impl TimeScale for Tai {}
impl TimeScale for Tt {}

trait OffsetProvider<Origin, Target>
where
    Origin: TimeScale,
    Target: TimeScale,
{
    fn offset(&self, origin: Origin, target: Target, epoch: f64) -> f64;
}

struct DefaultOffsetProvider;

const D_TAI_TT: f64 = 32.184;

impl OffsetProvider<Tai, Tt> for DefaultOffsetProvider {
    fn offset(&self, _origin: Tai, _target: Tt, _epoch: f64) -> f64 {
        D_TAI_TT
    }
}

impl OffsetProvider<Tt, Tai> for DefaultOffsetProvider {
    fn offset(&self, _origin: Tt, _target: Tai, _epoch: f64) -> f64 {
        -D_TAI_TT
    }
}

#[derive(Debug)]
struct Time<T: TimeScale + Copy> {
    scale: T,
    epoch: f64,
}

impl<T: TimeScale + Copy> Time<T> {
    fn to_scale<S: TimeScale + Copy>(&self, scale: S) -> Time<S>
    where
        DefaultOffsetProvider: OffsetProvider<T, S>,
    {
        self.to_scale_with_provider(scale, &DefaultOffsetProvider)
    }
        
    fn to_scale_with_provider<S: TimeScale + Copy, P: OffsetProvider<T, S>>(
        &self,
        scale: S,
        p: &P,
    ) -> Time<S> {
        Time {scale, epoch: self.epoch + p.offset(self.scale, scale, self.epoch) }
    }
}

fn main() {
    let offset = DefaultOffsetProvider.offset(Tai, Tt, 0.0);
    println!("{}", offset);
    let t = Time {
        scale: Tai,
        epoch: 0.0,
    };
    let t1 = t.to_scale(Tt);
    println!("{:?}", t1)
}

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions