summaryrefslogtreecommitdiffstats
path: root/common/netprotocol/src/convert.rs
blob: a7f866fa418a5f3b7dbe4330835dddabf4ec07c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// -*- coding: utf-8 -*-

use crate::time::{DateTime, UTCTimestamp, UTCTransformations};
use anyhow as ah;
use duration_string::DurationString;
use std::time::Duration;

pub fn u32_unpack(buf: &[u8]) -> u32 {
    assert_eq!(buf.len(), 4);
    u32::from_le_bytes(buf.try_into().unwrap())
}

pub fn u32_pack(v: u32) -> [u8; 4] {
    v.to_le_bytes()
}

pub fn u64_unpack(buf: &[u8]) -> u64 {
    assert_eq!(buf.len(), 8);
    u64::from_le_bytes(buf.try_into().unwrap())
}

pub fn u64_pack(v: u64) -> [u8; 8] {
    v.to_le_bytes()
}

pub fn u128_unpack(buf: &[u8]) -> u128 {
    assert_eq!(buf.len(), 16);
    u128::from_le_bytes(buf.try_into().unwrap())
}

pub fn u128_pack(v: u128) -> [u8; 16] {
    v.to_le_bytes()
}

pub fn f32_to_u32(v: f32) -> ah::Result<u32> {
    if !v.is_finite() {
        return Err(ah::format_err!("f32 value is infinite."));
    }
    if v.is_subnormal() {
        return Err(ah::format_err!("f32 value is subnormal."));
    }
    Ok(v.to_bits())
}

pub fn f32_to_u128(v: f32) -> ah::Result<u128> {
    f32_to_u32(v).map(|v| v as u128)
}

pub fn u32_to_f32(v: u32) -> ah::Result<f32> {
    let v = f32::from_bits(v);
    if !v.is_finite() {
        return Err(ah::format_err!("u32 value is an infinite f32."));
    }
    if v.is_subnormal() {
        return Err(ah::format_err!("u32 value is a subnormal f32."));
    }
    Ok(v)
}

pub fn u128_to_f32(v: u128) -> ah::Result<f32> {
    if v > u32::MAX as u128 {
        return Err(ah::format_err!("u128 value is not a valid f32."));
    }
    u32_to_f32(v as u32)
}

pub fn duration_to_u128(v: Duration) -> ah::Result<u128> {
    let v = v.as_millis();
    if v > u64::MAX as u128 {
        return Err(ah::format_err!("Duration value is bigger than u64."));
    }
    Ok(v)
}

pub fn u128_to_duration(v: u128) -> ah::Result<Duration> {
    if v > u64::MAX as u128 {
        return Err(ah::format_err!("Duration u128 value is bigger than u64."));
    }
    Ok(Duration::from_millis(v as u64))
}

pub fn duration_to_string(dur: Duration) -> String {
    DurationString::from(dur).into()
}

pub fn string_to_duration(dur: &str) -> ah::Result<Duration> {
    if let Ok(dur) = dur.parse::<DurationString>() {
        Ok(dur.into())
    } else {
        Err(ah::format_err!("Cannot parse Duration string."))
    }
}

pub fn datetime_to_u64(dt: DateTime) -> u64 {
    dt.as_timestamp().as_secs()
}

pub fn u64_to_datetime(dt: u64) -> ah::Result<DateTime> {
    Ok(DateTime::from_timestamp(UTCTimestamp::from_secs(dt)))
}

// vim: ts=4 sw=4 expandtab
bues.ch cgit interface