///|
pub suberror TdmsError {
Invalid(String)
Unsupported(String)
Budget(String)
} derive(Debug)
///|
fn demand(ok : Bool, message : String) -> Unit raise TdmsError {
if !ok {
raise Invalid(message)
}
}
///|
pub(all) enum DataType {
I8
I16
I32
I64
U8
U16
U32
U64
F32
F64
Text
Boolean
Time
} derive(Eq, Debug)
///|
pub(all) struct Timestamp {
seconds : Int64
fractions : UInt64
} derive(Eq, Debug)
///|
pub(all) enum Value {
Signed(Int64)
Unsigned(UInt64)
Real(Double)
Textual(String)
Logical(Bool)
Instant(Timestamp)
} derive(Eq, Debug)
///|
pub(all) struct Property {
name : String
kind : DataType
value : Value
} derive(Eq, Debug)
///|
pub(all) struct Limits {
max_bytes : Int32
max_segments : Int32
max_objects : Int32
max_properties : Int32
max_string_bytes : Int32
max_samples : Int32
} derive(Eq, Debug)
///|
pub fn Limits::default() -> Limits {
{
max_bytes: 64 * 1024 * 1024,
max_segments: 10000,
max_objects: 10000,
max_properties: 100000,
max_string_bytes: 1024 * 1024,
max_samples: 4000000,
}
}
///|
fn Limits::validate(self : Limits) -> Unit raise TdmsError {
demand(
self.max_bytes >= 28 &&
self.max_segments > 0 &&
self.max_objects > 0 &&
self.max_properties >= 0 &&
self.max_string_bytes >= 0 &&
self.max_samples >= 0,
"invalid resource limits",
)
}
///|
pub fn DataType::code(self : DataType) -> UInt32 {
match self {
I8 => 1U
I16 => 2U
I32 => 3U
I64 => 4U
U8 => 5U
U16 => 6U
U32 => 7U
U64 => 8U
F32 => 9U
F64 => 10U
Text => 32U
Boolean => 33U
Time => 68U
}
}
///|
pub fn data_type(code : UInt32) -> DataType raise TdmsError {
match code {
1U => I8
2U => I16
3U => I32
4U => I64
5U => U8
6U => U16
7U => U32
8U => U64
9U | 0x19U => F32
10U | 0x1AU => F64
32U => Text
33U => Boolean
68U => Time
_ => raise Unsupported("TDMS data type \{code}")
}
}
///|
pub fn DataType::width(self : DataType) -> Int32? {
match self {
I8 | U8 | Boolean => Some(1)
I16 | U16 => Some(2)
I32 | U32 | F32 => Some(4)
I64 | U64 | F64 => Some(8)
Time => Some(16)
Text => None
}
}
///|
fn Value::validate(self : Value, kind : DataType) -> Unit raise TdmsError {
let ok = match (kind, self) {
(I8, Signed(n)) => n >= -128L && n <= 127L
(I16, Signed(n)) => n >= -32768L && n <= 32767L
(I32, Signed(n)) => n >= -2147483648L && n <= 2147483647L
(I64, Signed(_)) => true
(U8, Unsigned(n)) => n <= 255UL
(U16, Unsigned(n)) => n <= 65535UL
(U32, Unsigned(n)) => n <= 4294967295UL
(U64, Unsigned(_)) => true
(F32, Real(n)) =>
n.is_nan() || n.is_inf() || !Float::from_double(n).is_inf()
(F64, Real(_)) => true
(Text, Textual(_)) | (Boolean, Logical(_)) | (Time, Instant(_)) => true
_ => false
}
demand(ok, "value does not fit declared type")
}
///|
pub fn Value::as_double(self : Value) -> Double raise TdmsError {
match self {
Signed(n) => n.to_double()
Unsigned(n) => n.to_double()
Real(n) => n
Logical(b) => if b { 1.0 } else { 0.0 }
_ => raise Invalid("channel is not numeric")
}
}
///|
pub extend DataType with @debug.Debug::{to_repr}
///|
pub extend DataType with Eq::{equal, not_equal}
///|
pub extend Timestamp with @debug.Debug::{to_repr}
///|
pub extend Timestamp with Eq::{equal, not_equal}
///|
pub extend Value with @debug.Debug::{to_repr}
///|
pub extend Value with Eq::{equal, not_equal}
///|
pub extend Property with @debug.Debug::{to_repr}
///|
pub extend Property with Eq::{equal, not_equal}
///|
pub extend Limits with @debug.Debug::{to_repr}
///|
pub extend Limits with Eq::{equal, not_equal}
///|
pub extend TdmsError with @debug.Debug::{to_repr}