rnet 0.3.1

Easily call into Rust from C# or other .net langauges.
Documentation
use chrono::{DateTime, Datelike, NaiveDate, NaiveDateTime, NaiveTime, Utc};

use crate::{hidden::GeneratorContext, FromNet, Net, ToNet};

const NANOS_PER_TICK: u64 = 100;
const TICKS_PER_SECOND: u64 = 1_000_000_000 / NANOS_PER_TICK;
const TICKS_PER_DAY: u64 = TICKS_PER_SECOND * 60 * 60 * 24;

unsafe impl Net for NaiveDateTime {
    type Raw = i64;

    fn gen_type(_ctx: &mut GeneratorContext) -> Box<str> {
        "DateTime".into()
    }

    fn gen_raw_type(_ctx: &mut GeneratorContext) -> Box<str> {
        "long".into()
    }

    fn is_nullable(_ctx: &mut GeneratorContext) -> bool {
        false
    }
}

unsafe impl FromNet for NaiveDateTime {
    unsafe fn from_raw(arg: Self::Raw) -> Self {
        let days = ((arg as u64) / TICKS_PER_DAY + 1) as i32;
        let nanos = ((arg as u64) % TICKS_PER_DAY) * NANOS_PER_TICK;
        NaiveDate::from_num_days_from_ce(days)
            .and_time(NaiveTime::from_hms(0, 0, 0) + chrono::Duration::nanoseconds(nanos as i64))
    }

    fn gen_marshal(_ctx: &mut GeneratorContext, arg: &str) -> Box<str> {
        format!("({}).Ticks", arg).into()
    }
}

unsafe impl ToNet for NaiveDateTime {
    fn into_raw(self) -> Self::Raw {
        let days = (self.num_days_from_ce() - 1) as i64;
        let nanos = (self.time() - NaiveTime::from_hms(0, 0, 0))
            .num_nanoseconds()
            .unwrap();
        (days * (TICKS_PER_DAY as i64)) + (nanos / (NANOS_PER_TICK as i64))
    }

    fn gen_marshal(_ctx: &mut GeneratorContext, arg: &str) -> Box<str> {
        format!("new DateTime({}, DateTimeKind.Unspecified)", arg).into()
    }
}

unsafe impl Net for DateTime<Utc> {
    type Raw = i64;

    fn gen_type(_ctx: &mut GeneratorContext) -> Box<str> {
        "DateTime".into()
    }

    fn gen_raw_type(_ctx: &mut GeneratorContext) -> Box<str> {
        "long".into()
    }

    fn is_nullable(_ctx: &mut GeneratorContext) -> bool {
        false
    }
}

unsafe impl FromNet for DateTime<Utc> {
    unsafe fn from_raw(arg: Self::Raw) -> Self {
        DateTime::from_utc(NaiveDateTime::from_raw(arg), Utc)
    }

    fn gen_marshal(_ctx: &mut GeneratorContext, arg: &str) -> Box<str> {
        format!("({}).ToUniversalTime().Ticks", arg).into()
    }
}

unsafe impl ToNet for DateTime<Utc> {
    fn into_raw(self) -> Self::Raw {
        self.naive_utc().into_raw()
    }

    fn gen_marshal(_ctx: &mut GeneratorContext, arg: &str) -> Box<str> {
        format!("new DateTime({}, DateTimeKind.Utc)", arg).into()
    }
}