From 12231fc210675687e3f61c0bae3320debd3ace1a Mon Sep 17 00:00:00 2001 From: Nickolas Fotopoulos Date: Wed, 17 Jul 2024 23:13:08 -0700 Subject: [PATCH] Add vector type support (ex: '100E') and fix bit handling * Rows can be of vector type, where each row has multiple of the same data type in the column. Bitmasks (32X) and strings (20A) are the most common examples, but others exist in the wild. * In more fully supporting repeats, revamped the bit handling. * Filled out the data type support and added round-trip read-write tests for all vector types. Weirdly, I couldn't get the u32 case to work and suspect a CFITSIO bug. Then again, all unsigned types are unofficial CFITSIO extensions beyond the FITS spec. * Removed conditionals for reads_col_impl and writes_col_impl; int is 32 bits and long long is consistently 64 bits on all machines and platforms. Only long is weird and special. --- CHANGELOG.md | 1 + fitsio/src/fitsfile.rs | 10 +- fitsio/src/hdu.rs | 4 +- fitsio/src/longnam.rs | 70 +++++++++- fitsio/src/tables.rs | 185 ++++++++++++++++++++++---- fitsio/src/types.rs | 3 +- fitsio/tests/test_bit_datatype.rs | 62 ++++++++- fitsio/tests/test_vector_datatypes.rs | 97 ++++++++++++++ 8 files changed, 384 insertions(+), 48 deletions(-) create mode 100644 fitsio/tests/test_vector_datatypes.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 7319589f..c755d124 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a ## [Unreleased] ### Added +* Support for vector data-types in reading and writing tables. ### Changed ### Removed diff --git a/fitsio/src/fitsfile.rs b/fitsio/src/fitsfile.rs index e2ad1727..2cba6592 100644 --- a/fitsio/src/fitsfile.rs +++ b/fitsio/src/fitsfile.rs @@ -368,6 +368,7 @@ impl FitsFile { for i in 0..num_cols { let mut name_buffer: Vec = vec![0; 71]; let mut type_buffer: Vec = vec![0; 71]; + let mut repeats: libc::c_long = 0; unsafe { fits_get_bcolparms( self.fptr.as_mut() as *mut _, @@ -375,7 +376,7 @@ impl FitsFile { name_buffer.as_mut_ptr(), ptr::null_mut(), type_buffer.as_mut_ptr(), - ptr::null_mut(), + &mut repeats as *mut libc::c_long, ptr::null_mut(), ptr::null_mut(), ptr::null_mut(), @@ -383,12 +384,13 @@ impl FitsFile { &mut status, ); } - - column_descriptions.push(ConcreteColumnDescription { + let mut col = ConcreteColumnDescription { name: stringutils::buf_to_string(&name_buffer)?, data_type: stringutils::buf_to_string(&type_buffer)? .parse::()?, - }); + }; + col.data_type.repeat = repeats as usize; + column_descriptions.push(col); } HduInfo::TableInfo { diff --git a/fitsio/src/hdu.rs b/fitsio/src/hdu.rs index 5c6b1e62..2cad26ea 100644 --- a/fitsio/src/hdu.rs +++ b/fitsio/src/hdu.rs @@ -761,7 +761,7 @@ impl FitsHdu { # } ``` */ - pub fn write_col_range>( + pub fn write_col_range + Clone>( &self, fits_file: &mut FitsFile, name: N, @@ -807,7 +807,7 @@ impl FitsHdu { # } ``` */ - pub fn write_col>( + pub fn write_col + Clone>( &self, fits_file: &mut FitsFile, name: N, diff --git a/fitsio/src/longnam.rs b/fitsio/src/longnam.rs index ed762f7e..23432b1b 100644 --- a/fitsio/src/longnam.rs +++ b/fitsio/src/longnam.rs @@ -5,15 +5,15 @@ #![allow(unused_imports, dead_code)] pub(crate) use crate::sys::{ - ffclos, ffcopy, ffcrim, ffcrtb, ffdcol, ffdhdu, ffflmd, ffgbcl, ffgcdw, ffgcno, ffgcvd, ffgcve, - ffgcvi, ffgcvj, ffgcvjj, ffgcvk, ffgcvs, ffgcvui, ffgcvuj, ffgcvujj, ffgcvuk, ffghdn, ffghdt, - ffgidm, ffgiet, ffgisz, ffgkyd, ffgkye, ffgkyj, ffgkyjj, ffgkyl, ffgkys, ffgncl, ffgnrw, ffgpv, - ffgsv, fficol, ffinit, ffmahd, ffmnhd, ffopen, ffpcl, ffpcls, ffphps, ffpky, ffpkyd, ffpkye, - ffpkys, ffppr, ffpss, ffrsim, ffthdu, fitsfile, LONGLONG, + ffclos, ffcopy, ffcrim, ffcrtb, ffdcol, ffdhdu, ffflmd, ffgbcl, ffgcdw, ffgcno, ffgcvb, ffgcvd, + ffgcve, ffgcvi, ffgcvj, ffgcvjj, ffgcvk, ffgcvs, ffgcvsb, ffgcvui, ffgcvuj, ffgcvujj, ffgcvuk, + ffgcx, ffghdn, ffghdt, ffgidm, ffgiet, ffgisz, ffgkyd, ffgkye, ffgkyj, ffgkyjj, ffgkyl, ffgkys, + ffgncl, ffgnrw, ffgpv, ffgsv, fficol, ffinit, ffmahd, ffmnhd, ffopen, ffpcl, ffpcls, ffpclx, + ffphps, ffpky, ffpkyd, ffpkye, ffpkys, ffppr, ffpss, ffrsim, ffthdu, fitsfile, LONGLONG, }; pub use libc::{ - c_char, c_double, c_float, c_int, c_long, c_short, c_uint, c_ulong, c_ulonglong, c_ushort, - c_void, + c_char, c_double, c_float, c_int, c_long, c_schar, c_short, c_uchar, c_uint, c_ulong, + c_ulonglong, c_ushort, c_void, }; pub(crate) unsafe fn fits_close_file(fptr: *mut fitsfile, status: *mut libc::c_int) -> c_int { @@ -132,6 +132,50 @@ pub(crate) unsafe fn fits_read_col_str( ) } +pub(crate) unsafe fn fits_read_col_bit( + fptr: *mut fitsfile, + colnum: c_int, + firstrow: LONGLONG, + firstbit: LONGLONG, + nbits: LONGLONG, + larray: *mut c_char, + status: *mut c_int, +) -> c_int { + ffgcx(fptr, colnum, firstrow, firstbit, nbits, larray, status) +} + +pub(crate) unsafe fn fits_read_col_byt( + fptr: *mut fitsfile, + colnum: c_int, + firstrow: LONGLONG, + firstelem: LONGLONG, + nelem: LONGLONG, + nulval: c_uchar, + array: *mut c_uchar, + anynul: *mut c_int, + status: *mut c_int, +) -> c_int { + ffgcvb( + fptr, colnum, firstrow, firstelem, nelem, nulval, array, anynul, status, + ) +} + +pub(crate) unsafe fn fits_read_col_sbyt( + fptr: *mut fitsfile, + colnum: c_int, + firstrow: LONGLONG, + firstelem: LONGLONG, + nelem: LONGLONG, + nulval: c_schar, + array: *mut c_schar, + anynul: *mut c_int, + status: *mut c_int, +) -> c_int { + ffgcvsb( + fptr, colnum, firstrow, firstelem, nelem, nulval, array, anynul, status, + ) +} + pub(crate) unsafe fn fits_read_col_sht( fptr: *mut fitsfile, colnum: c_int, @@ -489,6 +533,18 @@ pub(crate) unsafe fn fits_write_col( ) } +pub(crate) unsafe fn fits_write_col_bit( + fptr: *mut fitsfile, + colnum: c_int, + firstrow: LONGLONG, + firstbit: c_long, + nbit: c_long, + larray: *mut c_char, + status: *mut c_int, +) -> c_int { + ffpclx(fptr, colnum, firstrow, firstbit, nbit, larray, status) +} + pub(crate) unsafe fn fits_write_col_str( fptr: *mut fitsfile, colnum: c_int, diff --git a/fitsio/src/tables.rs b/fitsio/src/tables.rs index dfca867b..a3885208 100644 --- a/fitsio/src/tables.rs +++ b/fitsio/src/tables.rs @@ -6,6 +6,7 @@ use crate::longnam::*; use crate::stringutils::status_to_string; use crate::types::DataType; use std::ffi; +use std::mem::size_of; use std::ops::Range; use std::ptr; use std::str::FromStr; @@ -57,7 +58,6 @@ macro_rules! reads_col_impl { .. }) => { let num_output_rows = range.end - range.start; - let mut out = vec![$nullval; num_output_rows]; let test_name = name.into(); let column_number = column_descriptions .iter() @@ -66,6 +66,13 @@ macro_rules! reads_col_impl { "Cannot find column {:?}", test_name )))?; + let col_desc = &column_descriptions[column_number]; + let repeat = if col_desc.data_type.typ == ColumnDataType::Bit { + col_desc.data_type.repeat / (size_of::<$t>() * 8) + } else { + col_desc.data_type.repeat + }; + let mut out = vec![$nullval; num_output_rows * repeat]; let mut status = 0; unsafe { $func( @@ -73,7 +80,7 @@ macro_rules! reads_col_impl { (column_number + 1) as i32, (range.start + 1) as i64, 1, - num_output_rows as _, + (num_output_rows * repeat) as _, $nullval, out.as_mut_ptr(), ptr::null_mut(), @@ -119,6 +126,12 @@ macro_rules! reads_col_impl { "Cannot find column {:?}", test_name )))?; + let repeat = column_descriptions[column_number].data_type.repeat; + if repeat > 1 { + unimplemented!( + "reading a single cell of a vector value (e.g., TFORM1 = 100E) is unimplemented. Call read_col() or read_col_range()." + ) + } let mut status = 0; unsafe { @@ -145,20 +158,83 @@ macro_rules! reads_col_impl { }; } +reads_col_impl!(u8, fits_read_col_byt, 0); +reads_col_impl!(i8, fits_read_col_sbyt, 0); reads_col_impl!(i16, fits_read_col_sht, 0); reads_col_impl!(u16, fits_read_col_usht, 0); reads_col_impl!(i32, fits_read_col_int, 0); reads_col_impl!(u32, fits_read_col_uint, 0); -reads_col_impl!(f32, fits_read_col_flt, 0.0); -reads_col_impl!(f64, fits_read_col_dbl, 0.0); -#[cfg(all(target_pointer_width = "64", not(target_os = "windows")))] -reads_col_impl!(i64, fits_read_col_lng, 0); -#[cfg(any(target_pointer_width = "32", target_os = "windows"))] reads_col_impl!(i64, fits_read_col_lnglng, 0); -#[cfg(all(target_pointer_width = "64", not(target_os = "windows")))] -reads_col_impl!(u64, fits_read_col_ulng, 0); -#[cfg(any(target_pointer_width = "32", target_os = "windows"))] reads_col_impl!(u64, fits_read_col_ulnglng, 0); +reads_col_impl!(f32, fits_read_col_flt, 0.0); +reads_col_impl!(f64, fits_read_col_dbl, 0.0); + +impl ReadsCol for bool { + fn read_col_range>( + fits_file: &mut FitsFile, + name: T, + range: &Range, + ) -> Result> { + match fits_file.fetch_hdu_info() { + Ok(HduInfo::TableInfo { + column_descriptions, + .. + }) => { + let num_output_rows = range.end - range.start; + let test_name = name.into(); + let column_number = column_descriptions + .iter() + .position(|ref desc| desc.name == test_name) + .ok_or(Error::Message(format!( + "Cannot find column {:?}", + test_name + )))?; + let col_desc = &column_descriptions[column_number]; + let repeat = col_desc.data_type.repeat; + let num_bits = num_output_rows * repeat; + + let mut out = vec![false; num_bits]; + let mut status = 0; + unsafe { + fits_read_col_bit( + fits_file.fptr.as_mut() as *mut _, + (column_number + 1) as i32, + (range.start + 1) as i64, + 1, + num_bits as _, + out.as_mut_ptr() as *mut c_char, + &mut status, + ); + } + + match status { + 0 => Ok(out), + 307 => Err(IndexError { + message: "given indices out of range".to_string(), + given: range.clone(), + } + .into()), + e => Err(FitsError { + status: e, + message: status_to_string(e).unwrap().unwrap(), + } + .into()), + } + } + Err(e) => Err(e), + _ => panic!("Unknown error occurred"), + } + } + + fn read_cell_value(fits_file: &mut FitsFile, name: T, idx: usize) -> Result + where + T: Into, + Self: Sized, + { + // XXX Ineffient but works + Self::read_col_range(fits_file, name, &(idx..idx + 1)).map(|v| v[0].clone()) + } +} impl ReadsCol for String { fn read_col_range>( @@ -257,7 +333,8 @@ pub trait WritesCol { { match fits_file.fetch_hdu_info() { Ok(HduInfo::TableInfo { .. }) => { - let row_range = 0..col_data.len(); + let num_rows = col_data.len(); + let row_range = 0..num_rows; Self::write_col_range(fits_file, hdu, col_name, col_data, &row_range) } Ok(HduInfo::ImageInfo { .. }) => Err("Cannot write column data to FITS image".into()), @@ -284,7 +361,7 @@ macro_rules! writes_col_impl { let colno = hdu.get_column_no(fits_file, col_name.into())?; // TODO: check that the column exists in the file let mut status = 0; - let n_elements = rows.end - rows.start; + let n_rows = rows.end - rows.start; unsafe { fits_write_col( fits_file.fptr.as_mut() as *mut _, @@ -292,7 +369,7 @@ macro_rules! writes_col_impl { (colno + 1) as _, (rows.start + 1) as _, 1, - n_elements as _, + n_rows as _, col_data.as_ptr() as *mut _, &mut status, ); @@ -312,19 +389,57 @@ macro_rules! writes_col_impl { }; } -writes_col_impl!(u32, DataType::TUINT); -#[cfg(all(target_pointer_width = "64", not(target_os = "windows")))] -writes_col_impl!(u64, DataType::TULONG); -#[cfg(any(target_pointer_width = "32", target_os = "windows"))] -writes_col_impl!(u64, DataType::TLONGLONG); +writes_col_impl!(u8, DataType::TBYTE); +writes_col_impl!(i8, DataType::TSBYTE); writes_col_impl!(i32, DataType::TINT); -#[cfg(all(target_pointer_width = "64", not(target_os = "windows")))] -writes_col_impl!(i64, DataType::TLONG); -#[cfg(any(target_pointer_width = "32", target_os = "windows"))] +writes_col_impl!(u32, DataType::TUINT); writes_col_impl!(i64, DataType::TLONGLONG); +writes_col_impl!(u64, DataType::TULONGLONG); writes_col_impl!(f32, DataType::TFLOAT); writes_col_impl!(f64, DataType::TDOUBLE); +impl WritesCol for bool { + fn write_col_range>( + fits_file: &mut FitsFile, + hdu: &FitsHdu, + col_name: T, + col_data: &[Self], + rows: &Range, + ) -> Result { + match fits_file.fetch_hdu_info() { + Ok(HduInfo::TableInfo { + column_descriptions, + .. + }) => { + let colno = hdu.get_column_no(fits_file, col_name.into())?; + // TODO: check that the column exists in the file + let col_desc = &column_descriptions[colno]; + let repeat = col_desc.data_type.repeat; + let num_bits = (rows.end - rows.start) * repeat; + + let mut status = 0; + unsafe { + fits_write_col_bit( + fits_file.fptr.as_mut() as *mut _, + (colno + 1) as _, + (rows.start + 1) as _, + 1, + num_bits as _, + col_data.as_ptr() as *mut _, + &mut status as *mut _, + ); + } + check_status(status).and_then(|_| fits_file.current_hdu()) + } + Ok(HduInfo::ImageInfo { .. }) => Err("Cannot write column data to FITS image".into()), + Ok(HduInfo::AnyInfo { .. }) => { + Err("Cannot determine HDU type, so cannot write column data".into()) + } + Err(e) => Err(e), + } + } +} + impl WritesCol for String { fn write_col_range>( fits_file: &mut FitsFile, @@ -538,12 +653,17 @@ impl From for String { pub enum ColumnDataType { Bit, Byte, + SignedByte, + Short, + UnsignedShort, Int, + Long, + UnsignedLong, Float, Text, Double, - Short, - Long, + LongLong, + UnsignedLongLong, String, } @@ -554,12 +674,16 @@ impl From for String { match orig { Bit => "X", Byte => "B", - Int => "J", + SignedByte => "S", + Short => "I", + UnsignedShort => "U", + Int | Long => "J", + UnsignedLong => "U", Float => "E", Text | String => "A", Double => "D", - Short => "I", - Long => "K", + LongLong => "K", + UnsignedLongLong => "W", } .to_string() } @@ -611,12 +735,16 @@ impl FromStr for ColumnDataDescription { let data_type = match data_type_char { 'X' => ColumnDataType::Bit, 'B' => ColumnDataType::Byte, + 'S' => ColumnDataType::SignedByte, 'E' => ColumnDataType::Float, 'J' => ColumnDataType::Int, 'D' => ColumnDataType::Double, 'I' => ColumnDataType::Short, - 'K' => ColumnDataType::Long, + 'K' => ColumnDataType::LongLong, 'A' => ColumnDataType::String, + 'U' => ColumnDataType::UnsignedShort, + 'V' => ColumnDataType::UnsignedLong, + 'W' => ColumnDataType::UnsignedLongLong, _ => panic!( "Have not implemented str -> ColumnDataType for {}", data_type_char @@ -668,8 +796,9 @@ macro_rules! datatype_into_impl { DataType::TINT => 31, DataType::TULONG => 40, DataType::TLONG => 41, - DataType::TLONGLONG => 81, DataType::TFLOAT => 42, + DataType::TULONGLONG => 80, + DataType::TLONGLONG => 81, DataType::TDOUBLE => 82, DataType::TCOMPLEX => 83, DataType::TDBLCOMPLEX => 163, diff --git a/fitsio/src/types.rs b/fitsio/src/types.rs index 77ce573b..fccf3698 100644 --- a/fitsio/src/types.rs +++ b/fitsio/src/types.rs @@ -16,8 +16,9 @@ pub enum DataType { TINT, TULONG, TLONG, - TLONGLONG, TFLOAT, + TULONGLONG, + TLONGLONG, TDOUBLE, TCOMPLEX, TDBLCOMPLEX, diff --git a/fitsio/tests/test_bit_datatype.rs b/fitsio/tests/test_bit_datatype.rs index 03d2209c..f5e01acb 100644 --- a/fitsio/tests/test_bit_datatype.rs +++ b/fitsio/tests/test_bit_datatype.rs @@ -4,17 +4,66 @@ use std::path::Path; use tempfile::Builder; #[test] -fn test_reading_bit_data_type() { +fn test_reading_bit_data_type_as_bool() { let source_file = Path::new("tests/fixtures/1065880128_01.mwaf"); let mut f = FitsFile::open(source_file).unwrap(); let table_hdu = f.hdu(1).unwrap(); - let flags: Vec = table_hdu.read_col(&mut f, "FLAGS").unwrap(); - assert_eq!(flags.len(), 1_849_344); + let flags: Vec = table_hdu.read_col(&mut f, "FLAGS").unwrap(); + assert_eq!(flags.len(), 1_849_344 * 32); } #[test] -fn test_writing_bit_data_type() { +fn test_reading_bit_data_type_as_u8() { + let source_file = Path::new("tests/fixtures/1065880128_01.mwaf"); + let mut f = FitsFile::open(source_file).unwrap(); + + let table_hdu = f.hdu(1).unwrap(); + let bitmasks: Vec = table_hdu.read_col(&mut f, "FLAGS").unwrap(); + assert_eq!(bitmasks.len(), 1_849_344 * 4); +} + +#[test] +fn test_reading_bit_data_type_as_u32() { + let source_file = Path::new("tests/fixtures/1065880128_01.mwaf"); + let mut f = FitsFile::open(source_file).unwrap(); + + let table_hdu = f.hdu(1).unwrap(); + let bitmasks: Vec = table_hdu.read_col(&mut f, "FLAGS").unwrap(); + assert_eq!(bitmasks.len(), 1_849_344); +} + +#[test] +fn test_writing_bit_data_type_as_bool() { + /* Create a temporary directory to work from */ + let tmp_dir = Builder::new().prefix("fitsio-").tempdir().unwrap(); + let file_path = tmp_dir.path().join("example.fits"); + + { + let mut fitsfile = FitsFile::create(&file_path).open().unwrap(); + + let data: Vec = vec![true, false].repeat(32); + let col = ColumnDescription::new("BITMASK") + .with_type(ColumnDataType::Bit) + .that_repeats(8) + .create() + .unwrap(); + let columns = &[col]; + let table_hdu = fitsfile.create_table("DATA", columns).unwrap(); + table_hdu + .write_col(&mut fitsfile, "BITMASK", &data) + .unwrap(); + } + + let mut f = FitsFile::open(file_path).unwrap(); + + let table_hdu = f.hdu("DATA").unwrap(); + let flags: Vec = table_hdu.read_col(&mut f, "BITMASK").unwrap(); + assert_eq!(flags.len(), 64); +} + +#[test] +fn test_writing_bit_data_type_as_u8() { /* Create a temporary directory to work from */ let tmp_dir = Builder::new().prefix("fitsio-").tempdir().unwrap(); let file_path = tmp_dir.path().join("example.fits"); @@ -22,9 +71,10 @@ fn test_writing_bit_data_type() { { let mut fitsfile = FitsFile::create(&file_path).open().unwrap(); - let data: Vec = (0..64).collect(); + let data: Vec = vec![0xa5].repeat(8); let col = ColumnDescription::new("BITMASK") .with_type(ColumnDataType::Bit) + .that_repeats(8) .create() .unwrap(); let columns = &[col]; @@ -37,6 +87,6 @@ fn test_writing_bit_data_type() { let mut f = FitsFile::open(file_path).unwrap(); let table_hdu = f.hdu("DATA").unwrap(); - let flags: Vec = dbg!(table_hdu.read_col(&mut f, "BITMASK").unwrap()); + let flags: Vec = table_hdu.read_col(&mut f, "BITMASK").unwrap(); assert_eq!(flags.len(), 64); } diff --git a/fitsio/tests/test_vector_datatypes.rs b/fitsio/tests/test_vector_datatypes.rs new file mode 100644 index 00000000..8db8e2f4 --- /dev/null +++ b/fitsio/tests/test_vector_datatypes.rs @@ -0,0 +1,97 @@ +use fitsio::tables::{ColumnDataType, ColumnDescription}; +use fitsio::FitsFile; +use tempfile::Builder; + +const NV: usize = 128; // vector size +const NR: usize = 3; // number of rows + +macro_rules! make_test { + ($func:ident, $t:ty, $dt:expr, $val:expr) => { + #[test] + fn $func() { + let tmp_dir = Builder::new().prefix("fitsio-").tempdir().unwrap(); + let file_path = tmp_dir.path().join("example.fits"); + + let orig_data: Vec<$t> = vec![$val].repeat(NV * NR); + { + let mut fitsfile = FitsFile::create(&file_path).open().unwrap(); + + let col = ColumnDescription::new("TEST") + .with_type($dt) + .that_repeats(NV) + .create() + .unwrap(); + let columns = &[col]; + let table_hdu = fitsfile.create_table("DATA", columns).unwrap(); + table_hdu + .write_col(&mut fitsfile, "TEST", &orig_data) + .unwrap(); + } + + let mut f = FitsFile::open(file_path).unwrap(); + + let table_hdu = f.hdu("DATA").unwrap(); + let data: Vec<$t> = table_hdu.read_col(&mut f, "TEST").unwrap(); + assert!(orig_data.iter().zip(&data).all(|(a, b)| a == b)); + } + }; +} + +make_test!( + test_read_write_vector_data_type_u8, + u8, + ColumnDataType::Byte, + 0xa5 +); + +make_test!( + test_read_write_vector_data_type_i8, + i8, + ColumnDataType::SignedByte, + 0x5a +); + +make_test!( + test_read_write_vector_data_type_i32, + i32, + ColumnDataType::Int, + 0x5a5a5a5a +); + +// Commented out u32, as CFITSIO will return error 412 (datatype conversion overflow) +// with any value over 16 bits(!?). Unsigned types are an unofficial CFITSIO extension anyway. + +// make_test!( +// test_read_write_vector_data_type_u32, +// u32, +// ColumnDataType::UnsignedLong, +// 0xa5a5a5a5 +// ); + +make_test!( + test_read_write_vector_data_type_u64, + u64, + ColumnDataType::UnsignedLongLong, + 0xa5a5a5a5_a5a5a5a5 +); + +make_test!( + test_read_write_vector_data_type_i64, + i64, + ColumnDataType::LongLong, + 0x5a5a5a5a_5a5a5a5a +); + +make_test!( + test_read_write_vector_data_type_f32, + f32, + ColumnDataType::Float, + 3.1415926535879323 +); + +make_test!( + test_read_write_vector_data_type_f64, + f64, + ColumnDataType::Double, + 3.1415926535879323 +);