use std::ffi::{CStr, c_char, c_double, c_int, c_void};
use asdf_core::yaml as asdf_yaml;
use crate::error_ffi::LogLevel;
pub type AsdfParserOptFlags = u64;
pub type AsdfEmitterOptFlags = u64;
pub type AsdfLogFields = u64;
pub mod parser_opt {
pub const EMIT_YAML_EVENTS: u64 = 1 << 0;
pub const BUFFER_TREE: u64 = 1 << 1;
}
pub mod emitter_opt {
pub const DEFAULT: u64 = 1 << 0;
pub const EMIT_EMPTY: u64 = 1 << 1;
pub const NO_BLOCK_CHECKSUM: u64 = 1 << 2;
pub const NO_BLOCK_INDEX: u64 = 1 << 3;
pub const EMIT_EMPTY_TREE: u64 = 1 << 4;
pub const NO_EMIT_EMPTY_TREE: u64 = 1 << 5;
pub const NO_EMIT_ASDF_LIBRARY: u64 = 1 << 6;
pub const LAST: u64 = 1 << 62;
}
pub mod log_field {
pub const LEVEL: u64 = 1 << 0;
pub const PACKAGE: u64 = 1 << 1;
pub const FILE: u64 = 1 << 2;
pub const LINE: u64 = 1 << 3;
pub const MSG: u64 = 1 << 4;
pub const ALL: u64 = LEVEL | PACKAGE | FILE | LINE | MSG;
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
#[repr(i32)]
pub enum AsdfArrayStorage {
#[default]
Default = 0,
Inline = 1,
Internal = 2,
External = 3,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
#[repr(i32)]
pub enum AsdfBlockDecompMode {
#[default]
Auto = 0,
Eager = 1,
Lazy = 2,
}
#[repr(C)]
#[derive(Debug)]
pub struct asdf_yaml_tag_handle_t {
pub handle: *const c_char,
pub prefix: *const c_char,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[repr(i32)]
pub enum AsdfEventType {
None = 0,
Begin,
AsdfVersion,
StandardVersion,
Comment,
TreeStart,
Yaml,
TreeEnd,
Block,
Padding,
BlockIndex,
End,
}
impl AsdfEventType {
pub fn name(self) -> &'static CStr {
match self {
AsdfEventType::None => c"ASDF_NONE_EVENT",
AsdfEventType::Begin => c"ASDF_BEGIN_EVENT",
AsdfEventType::AsdfVersion => c"ASDF_ASDF_VERSION_EVENT",
AsdfEventType::StandardVersion => c"ASDF_STANDARD_VERSION_EVENT",
AsdfEventType::Comment => c"ASDF_COMMENT_EVENT",
AsdfEventType::TreeStart => c"ASDF_TREE_START_EVENT",
AsdfEventType::Yaml => c"ASDF_YAML_EVENT",
AsdfEventType::TreeEnd => c"ASDF_TREE_END_EVENT",
AsdfEventType::Block => c"ASDF_BLOCK_EVENT",
AsdfEventType::Padding => c"ASDF_PADDING_EVENT",
AsdfEventType::BlockIndex => c"ASDF_BLOCK_INDEX_EVENT",
AsdfEventType::End => c"ASDF_END_EVENT",
}
}
}
impl AsdfEventType {
pub fn from_i32(value: i32) -> Option<Self> {
(0..ASDF_EVENT_TYPE_COUNT)
.contains(&value)
.then(|| unsafe { std::mem::transmute::<i32, AsdfEventType>(value) })
}
}
pub const ASDF_EVENT_TYPE_COUNT: i32 = 12;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[repr(i32)]
pub enum AsdfYamlEventType {
None = 0,
StreamStart,
StreamEnd,
DocumentStart,
DocumentEnd,
MappingStart,
MappingEnd,
SequenceStart,
SequenceEnd,
Scalar,
Alias,
}
impl AsdfYamlEventType {
pub fn text(self) -> &'static CStr {
match self {
AsdfYamlEventType::None => c"",
AsdfYamlEventType::StreamStart => c"+STR",
AsdfYamlEventType::StreamEnd => c"-STR",
AsdfYamlEventType::DocumentStart => c"+DOC",
AsdfYamlEventType::DocumentEnd => c"-DOC",
AsdfYamlEventType::MappingStart => c"+MAP",
AsdfYamlEventType::MappingEnd => c"-MAP",
AsdfYamlEventType::SequenceStart => c"+SEQ",
AsdfYamlEventType::SequenceEnd => c"-SEQ",
AsdfYamlEventType::Scalar => c"=VAL",
AsdfYamlEventType::Alias => c"=ALI",
}
}
}
#[repr(C)]
#[derive(Debug)]
pub struct asdf_tree_info_t {
pub start: usize,
pub end: usize,
pub buf: *const c_char,
}
#[repr(C)]
#[derive(Debug)]
pub struct asdf_block_header_t {
pub header_size: u16,
pub flags: u32,
pub compression: [u8; 4],
pub allocated_size: u64,
pub used_size: u64,
pub data_size: u64,
pub checksum: [u8; 16],
}
#[repr(C)]
#[derive(Debug)]
pub struct asdf_block_info_t {
pub index: usize,
pub header_pos: i64,
pub data_pos: i64,
pub header: asdf_block_header_t,
}
#[repr(C)]
#[derive(Debug)]
pub struct asdf_log_cfg_t {
pub stream: *mut c_void,
pub level: LogLevel,
pub fields: AsdfLogFields,
pub no_color: bool,
}
#[repr(C)]
#[derive(Debug)]
pub struct asdf_parser_cfg_t {
pub flags: AsdfParserOptFlags,
pub log: *mut asdf_log_cfg_t,
}
#[repr(C)]
#[derive(Debug)]
pub struct asdf_emitter_cfg_t {
pub flags: AsdfEmitterOptFlags,
pub tag_handles: *mut asdf_yaml_tag_handle_t,
pub inline_ndarray_warning_thresh: usize,
pub array_storage: AsdfArrayStorage,
}
#[repr(C)]
#[derive(Debug)]
pub struct asdf_decomp_cfg_t {
pub mode: AsdfBlockDecompMode,
pub max_memory_bytes: usize,
pub max_memory_threshold: c_double,
pub chunk_size: usize,
pub tmp_dir: *const c_char,
}
#[repr(C)]
#[derive(Debug)]
pub struct asdf_config_t {
pub parser: asdf_parser_cfg_t,
pub emitter: asdf_emitter_cfg_t,
pub log: asdf_log_cfg_t,
pub decomp: asdf_decomp_cfg_t,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[repr(i32)]
pub enum AsdfValueType {
Unknown = 0,
Sequence,
Mapping,
Scalar,
String,
Bool,
Null,
Int8,
Int16,
Int32,
Int64,
Uint8,
Uint16,
Uint32,
Uint64,
Float,
Double,
Extension,
}
impl AsdfValueType {
pub fn from_i32(value: i32) -> Option<Self> {
(AsdfValueType::Unknown as i32..=AsdfValueType::Extension as i32)
.contains(&value)
.then(|| unsafe { std::mem::transmute::<i32, AsdfValueType>(value) })
}
}
impl From<asdf_yaml::ValueType> for AsdfValueType {
fn from(v: asdf_yaml::ValueType) -> Self {
use asdf_yaml::ValueType as V;
match v {
V::Unknown => AsdfValueType::Unknown,
V::Sequence => AsdfValueType::Sequence,
V::Mapping => AsdfValueType::Mapping,
V::Scalar => AsdfValueType::Scalar,
V::String => AsdfValueType::String,
V::Bool => AsdfValueType::Bool,
V::Null => AsdfValueType::Null,
V::Int8 => AsdfValueType::Int8,
V::Int16 => AsdfValueType::Int16,
V::Int32 => AsdfValueType::Int32,
V::Int64 => AsdfValueType::Int64,
V::Uint8 => AsdfValueType::Uint8,
V::Uint16 => AsdfValueType::Uint16,
V::Uint32 => AsdfValueType::Uint32,
V::Uint64 => AsdfValueType::Uint64,
V::Float => AsdfValueType::Float,
V::Double => AsdfValueType::Double,
V::Extension => AsdfValueType::Extension,
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[repr(i32)]
pub enum AsdfValueErr {
Unknown = -2,
NotFound = -1,
Ok = 0,
TypeMismatch = 1,
ParseFailure = 2,
EmitFailure = 3,
Overflow = 4,
Oom = 5,
ReadOnly = 6,
}
pub use crate::ndarray_ffi::NdarrayErr as AsdfNdarrayErr;
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
#[repr(i32)]
pub enum AsdfYamlNodeStyle {
#[default]
Auto = 0,
Flow = 1,
Block = 2,
}
#[repr(C)]
#[derive(Debug)]
pub struct asdf_mapping_iter_t {
pub key: *const c_char,
pub value: *mut c_void,
}
#[repr(C)]
#[derive(Debug)]
pub struct asdf_find_iter_t {
pub value: *mut c_void,
}
#[repr(C)]
#[derive(Debug)]
pub struct asdf_sequence_iter_t {
pub value: *mut c_void,
pub index: c_int,
}
#[repr(C)]
#[derive(Debug)]
pub struct asdf_container_iter_t {
pub key: *const c_char,
pub index: c_int,
pub value: *mut c_void,
}
#[cfg(test)]
mod tests {
use super::*;
use std::mem::{align_of, offset_of, size_of};
#[test]
fn value_err_discriminants_span_zero() {
assert_eq!(AsdfValueErr::Unknown as i32, -2);
assert_eq!(AsdfValueErr::NotFound as i32, -1);
assert_eq!(AsdfValueErr::Ok as i32, 0);
assert_eq!(AsdfValueErr::TypeMismatch as i32, 1);
assert_eq!(AsdfValueErr::ReadOnly as i32, 6);
}
#[test]
fn value_type_discriminants_are_sequential_from_zero() {
assert_eq!(AsdfValueType::Unknown as i32, 0);
assert_eq!(AsdfValueType::Sequence as i32, 1);
assert_eq!(AsdfValueType::Mapping as i32, 2);
assert_eq!(AsdfValueType::Scalar as i32, 3);
assert_eq!(AsdfValueType::String as i32, 4);
assert_eq!(AsdfValueType::Extension as i32, 17);
}
#[test]
fn option_flags_are_bit_positions() {
assert_eq!(parser_opt::EMIT_YAML_EVENTS, 1);
assert_eq!(parser_opt::BUFFER_TREE, 2);
assert_eq!(emitter_opt::DEFAULT, 1);
assert_eq!(emitter_opt::EMIT_EMPTY, 2);
assert_eq!(emitter_opt::NO_EMIT_ASDF_LIBRARY, 64);
assert_eq!(log_field::ALL, 31);
}
#[test]
fn storage_and_decomp_modes_match_the_header() {
assert_eq!(AsdfArrayStorage::Default as i32, 0);
assert_eq!(AsdfArrayStorage::External as i32, 3);
assert_eq!(AsdfBlockDecompMode::Auto as i32, 0);
assert_eq!(AsdfBlockDecompMode::Lazy as i32, 2);
}
#[test]
fn config_nests_its_parts_in_declaration_order() {
assert_eq!(offset_of!(asdf_config_t, parser), 0);
assert!(offset_of!(asdf_config_t, emitter) >= size_of::<asdf_parser_cfg_t>());
assert!(offset_of!(asdf_config_t, log) > offset_of!(asdf_config_t, emitter));
assert!(offset_of!(asdf_config_t, decomp) > offset_of!(asdf_config_t, log));
}
#[test]
fn iterator_heads_start_with_their_public_fields() {
assert_eq!(offset_of!(asdf_mapping_iter_t, key), 0);
assert_eq!(offset_of!(asdf_sequence_iter_t, value), 0);
assert_eq!(offset_of!(asdf_container_iter_t, key), 0);
assert_eq!(offset_of!(asdf_find_iter_t, value), 0);
assert_eq!(align_of::<asdf_mapping_iter_t>(), align_of::<*const c_char>());
}
#[test]
fn value_types_convert_from_the_engine() {
assert_eq!(AsdfValueType::from(asdf_yaml::ValueType::Uint8), AsdfValueType::Uint8);
assert_eq!(AsdfValueType::from(asdf_yaml::ValueType::Double), AsdfValueType::Double);
assert_eq!(AsdfValueType::from(asdf_yaml::ValueType::Null), AsdfValueType::Null);
}
}