diff --git a/questdb-rs-ffi/Cargo.lock b/questdb-rs-ffi/Cargo.lock index 548c0f94..bb6cb8ab 100644 --- a/questdb-rs-ffi/Cargo.lock +++ b/questdb-rs-ffi/Cargo.lock @@ -60,13 +60,13 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "dns-lookup" -version = "2.1.1" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf5597a4b7fe5275fc9dcf88ce26326bc8e4cb87d0130f33752d4c5f717793cf" +checksum = "853d5bcf0b73bd5e6d945b976288621825c7166e9f06c5a035ae1aaf42d1b64f" dependencies = [ "cfg-if", "libc", - "socket2 0.6.0", + "socket2", "windows-sys 0.60.2", ] @@ -217,13 +217,12 @@ dependencies = [ "ring", "rustls", "rustls-native-certs", - "rustls-pemfile", "rustls-pki-types", "ryu", "serde", "serde_json", "slugify", - "socket2 0.5.10", + "socket2", "ureq", "webpki-roots", "winapi", @@ -313,9 +312,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" dependencies = [ "openssl-probe", "rustls-pki-types", @@ -323,15 +322,6 @@ dependencies = [ "security-framework", ] -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "rustls-pki-types" version = "1.12.0" @@ -450,22 +440,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "socket2" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -505,24 +485,22 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "3.0.12" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f0fde9bc91026e381155f8c67cb354bcd35260b2f4a29bcc84639f762760c39" +checksum = "99ba1025f18a4a3fc3e9b48c868e9beb4f24f4b4b1a325bada26bd4119f46537" dependencies = [ "base64", "log", "percent-encoding", - "rustls-pemfile", - "rustls-pki-types", "ureq-proto", "utf-8", ] [[package]] name = "ureq-proto" -version = "0.4.2" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59db78ad1923f2b1be62b6da81fe80b173605ca0d57f85da2e005382adf693f7" +checksum = "60b4531c118335662134346048ddb0e54cc86bd7e81866757873055f0e38f5d2" dependencies = [ "base64", "http", @@ -562,9 +540,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" +checksum = "32b130c0d2d49f8b6889abc456e795e82525204f27c42cf767cf0d7734e089b8" dependencies = [ "rustls-pki-types", ] @@ -606,15 +584,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-sys" version = "0.60.2" diff --git a/questdb-rs-ffi/Cargo.toml b/questdb-rs-ffi/Cargo.toml index 5cf2c27e..44666669 100644 --- a/questdb-rs-ffi/Cargo.toml +++ b/questdb-rs-ffi/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "questdb-rs-ffi" version = "5.1.0" -edition = "2021" +edition = "2024" publish = false [lib] diff --git a/questdb-rs-ffi/src/lib.rs b/questdb-rs-ffi/src/lib.rs index 03be44a7..ab3fe28b 100644 --- a/questdb-rs-ffi/src/lib.rs +++ b/questdb-rs-ffi/src/lib.rs @@ -34,12 +34,11 @@ use std::slice; use std::str; use questdb::{ - ingress, + Error, ErrorCode, ingress, ingress::{ Buffer, CertificateAuthority, ColumnName, Protocol, Sender, SenderBuilder, TableName, TimestampMicros, TimestampNanos, }, - Error, ErrorCode, }; mod ndarr; @@ -373,31 +372,35 @@ impl From for CertificateAuthority { } /** Error code categorizing the error. */ -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_error_get_code( error: *const line_sender_error, ) -> line_sender_error_code { - (*error).0.code().into() + unsafe { (*error).0.code().into() } } /// UTF-8 encoded error message. Never returns NULL. /// The `len_out` argument is set to the number of bytes in the string. /// The string is NOT null-terminated. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_error_msg( error: *const line_sender_error, len_out: *mut size_t, ) -> *const c_char { - let msg: &str = (*error).0.msg(); - *len_out = msg.len(); - msg.as_ptr() as *mut c_char + unsafe { + let msg: &str = (*error).0.msg(); + *len_out = msg.len(); + msg.as_ptr() as *const c_char + } } /// Clean up the error. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_error_free(error: *mut line_sender_error) { - if !error.is_null() { - drop(Box::from_raw(error)); + unsafe { + if !error.is_null() { + drop(Box::from_raw(error)); + } } } @@ -448,10 +451,12 @@ fn describe_buf(buf: &[u8]) -> String { unsafe fn set_err_out(err_out: *mut *mut line_sender_error, code: ErrorCode, msg: String) { let err = line_sender_error(Error::new(code, msg)); let err_ptr = Box::into_raw(Box::new(err)); - *err_out = err_ptr; + unsafe { + *err_out = err_ptr; + } } -unsafe fn unwrap_utf8_or_str(buf: &[u8]) -> Result<&str, String> { +fn unwrap_utf8_or_str(buf: &[u8]) -> Result<&str, String> { match str::from_utf8(buf) { Ok(str_ref) => Ok(str_ref), Err(u8err) => { @@ -486,7 +491,7 @@ unsafe fn unwrap_utf8(buf: &[u8], err_out: *mut *mut line_sender_error) -> Optio match unwrap_utf8_or_str(buf) { Ok(str_ref) => Some(str_ref), Err(msg) => { - set_err_out(err_out, ErrorCode::InvalidUtf8, msg); + unsafe { set_err_out(err_out, ErrorCode::InvalidUtf8, msg) }; None } } @@ -499,36 +504,40 @@ unsafe fn unwrap_utf8(buf: &[u8], err_out: *mut *mut line_sender_error) -> Optio /// @param[in] buf UTF-8 encoded buffer. Need not be null-terminated. /// @param[out] err_out Set on error. /// @return true on success, false on error. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_utf8_init( string: *mut line_sender_utf8, len: size_t, buf: *const c_char, err_out: *mut *mut line_sender_error, ) -> bool { - let slice = slice::from_raw_parts(buf as *const u8, len); - if let Some(str_ref) = unwrap_utf8(slice, err_out) { - (*string).len = str_ref.len(); - (*string).buf = str_ref.as_ptr() as *const c_char; - true - } else { - false + unsafe { + let slice = slice::from_raw_parts(buf as *const u8, len); + if let Some(str_ref) = unwrap_utf8(slice, err_out) { + (*string).len = str_ref.len(); + (*string).buf = str_ref.as_ptr() as *const c_char; + true + } else { + false + } } } -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_utf8_assert( len: size_t, buf: *const c_char, ) -> line_sender_utf8 { - let slice = slice::from_raw_parts(buf as *const u8, len); - match unwrap_utf8_or_str(slice) { - Ok(str_ref) => line_sender_utf8 { - len: str_ref.len(), - buf: str_ref.as_ptr() as *const c_char, - }, - Err(msg) => { - panic!("{}", msg); + unsafe { + let slice = slice::from_raw_parts(buf as *const u8, len); + match unwrap_utf8_or_str(slice) { + Ok(str_ref) => line_sender_utf8 { + len: str_ref.len(), + buf: str_ref.as_ptr() as *const c_char, + }, + Err(msg) => { + panic!("{}", msg); + } } } } @@ -546,9 +555,11 @@ pub struct line_sender_table_name { impl line_sender_table_name { unsafe fn as_name<'a>(&self) -> TableName<'a> { - let str_name = - str::from_utf8_unchecked(slice::from_raw_parts(self.buf as *const u8, self.len)); - TableName::new_unchecked(str_name) + unsafe { + let str_name = + str::from_utf8_unchecked(slice::from_raw_parts(self.buf as *const u8, self.len)); + TableName::new_unchecked(str_name) + } } } @@ -565,9 +576,11 @@ pub struct line_sender_column_name { impl line_sender_column_name { unsafe fn as_name<'a>(&self) -> ColumnName<'a> { - let str_name = - str::from_utf8_unchecked(slice::from_raw_parts(self.buf as *const u8, self.len)); - ColumnName::new_unchecked(str_name) + unsafe { + let str_name = + str::from_utf8_unchecked(slice::from_raw_parts(self.buf as *const u8, self.len)); + ColumnName::new_unchecked(str_name) + } } } @@ -579,40 +592,44 @@ impl line_sender_column_name { /// @param[in] buf UTF-8 encoded buffer. Need not be null-terminated. /// @param[out] err_out Set on error. /// @return true on success, false on error. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_table_name_init( name: *mut line_sender_table_name, len: size_t, buf: *const c_char, err_out: *mut *mut line_sender_error, ) -> bool { - let mut u8str = line_sender_utf8 { - len: 0usize, - buf: ptr::null_mut(), - }; - if !line_sender_utf8_init(&mut u8str, len, buf, err_out) { - return false; - } + unsafe { + let mut u8str = line_sender_utf8 { + len: 0usize, + buf: ptr::null_mut(), + }; + if !line_sender_utf8_init(&mut u8str, len, buf, err_out) { + return false; + } - let str_name = str::from_utf8_unchecked(slice::from_raw_parts(buf as *const u8, len)); + let str_name = str::from_utf8_unchecked(slice::from_raw_parts(buf as *const u8, len)); - bubble_err_to_c!(err_out, TableName::new(str_name)); + bubble_err_to_c!(err_out, TableName::new(str_name)); - (*name).len = len; - (*name).buf = buf; - true + (*name).len = len; + (*name).buf = buf; + true + } } -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_table_name_assert( len: size_t, buf: *const c_char, ) -> line_sender_table_name { - let u8str = line_sender_utf8_assert(len, buf); - match TableName::new(u8str.as_str()) { - Ok(_) => line_sender_table_name { len, buf }, - Err(msg) => { - panic!("{}", msg); + unsafe { + let u8str = line_sender_utf8_assert(len, buf); + match TableName::new(u8str.as_str()) { + Ok(_) => line_sender_table_name { len, buf }, + Err(msg) => { + panic!("{}", msg); + } } } } @@ -625,40 +642,44 @@ pub unsafe extern "C" fn line_sender_table_name_assert( /// @param[in] buf UTF-8 encoded buffer. Need not be null-terminated. /// @param[out] err_out Set on error. /// @return true on success, false on error. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_column_name_init( name: *mut line_sender_column_name, len: size_t, buf: *const c_char, err_out: *mut *mut line_sender_error, ) -> bool { - let mut u8str = line_sender_utf8 { - len: 0usize, - buf: ptr::null_mut(), - }; - if !line_sender_utf8_init(&mut u8str, len, buf, err_out) { - return false; - } + unsafe { + let mut u8str = line_sender_utf8 { + len: 0usize, + buf: ptr::null_mut(), + }; + if !line_sender_utf8_init(&mut u8str, len, buf, err_out) { + return false; + } - let str_name = str::from_utf8_unchecked(slice::from_raw_parts(buf as *const u8, len)); + let str_name = str::from_utf8_unchecked(slice::from_raw_parts(buf as *const u8, len)); - bubble_err_to_c!(err_out, ColumnName::new(str_name)); + bubble_err_to_c!(err_out, ColumnName::new(str_name)); - (*name).len = len; - (*name).buf = buf; - true + (*name).len = len; + (*name).buf = buf; + true + } } -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_column_name_assert( len: size_t, buf: *const c_char, -) -> line_sender_table_name { - let u8str = line_sender_utf8_assert(len, buf); - match ColumnName::new(u8str.as_str()) { - Ok(_) => line_sender_table_name { len, buf }, - Err(msg) => { - panic!("{}", msg); +) -> line_sender_column_name { + unsafe { + let u8str = line_sender_utf8_assert(len, buf); + match ColumnName::new(u8str.as_str()) { + Ok(_) => line_sender_column_name { len, buf }, + Err(msg) => { + panic!("{}", msg); + } } } } @@ -669,7 +690,7 @@ pub struct line_sender_buffer(Buffer); /// Construct a `line_sender_buffer` with a `max_name_len` of `127`, which is the /// same as the QuestDB server default. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_new( version: ProtocolVersion, ) -> *mut line_sender_buffer { @@ -682,7 +703,7 @@ pub unsafe extern "C" fn line_sender_buffer_new( /// the QuestDB server you're connecting to. /// If the server does not configure it, the default is `127`, and you can /// call `line_sender_buffer_new()` instead. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_with_max_name_len( version: ProtocolVersion, max_name_len: size_t, @@ -692,47 +713,53 @@ pub unsafe extern "C" fn line_sender_buffer_with_max_name_len( } /// Release the `line_sender_buffer` object. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_free(buffer: *mut line_sender_buffer) { - if !buffer.is_null() { - drop(Box::from_raw(buffer)); + unsafe { + if !buffer.is_null() { + drop(Box::from_raw(buffer)); + } } } unsafe fn unwrap_buffer<'a>(buffer: *const line_sender_buffer) -> &'a Buffer { - &(*buffer).0 + unsafe { &(*buffer).0 } } unsafe fn unwrap_buffer_mut<'a>(buffer: *mut line_sender_buffer) -> &'a mut Buffer { - &mut (*buffer).0 + unsafe { &mut (*buffer).0 } } /// Create a new copy of the buffer. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_clone( buffer: *const line_sender_buffer, ) -> *mut line_sender_buffer { - let new_buffer = unwrap_buffer(buffer).clone(); - Box::into_raw(Box::new(line_sender_buffer(new_buffer))) + unsafe { + let new_buffer = unwrap_buffer(buffer).clone(); + Box::into_raw(Box::new(line_sender_buffer(new_buffer))) + } } /// Pre-allocate to ensure the buffer has enough capacity for at least the /// specified additional byte count. This may be rounded up. /// This does not allocate if such additional capacity is already satisfied. /// See: `capacity`. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_reserve( buffer: *mut line_sender_buffer, additional: size_t, ) { - let buffer = unwrap_buffer_mut(buffer); - buffer.reserve(additional); + unsafe { + let buffer = unwrap_buffer_mut(buffer); + buffer.reserve(additional); + } } /// Get the current capacity of the buffer. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_capacity(buffer: *const line_sender_buffer) -> size_t { - unwrap_buffer(buffer).capacity() + unsafe { unwrap_buffer(buffer).capacity() } } /// Mark a rewind point. @@ -740,66 +767,80 @@ pub unsafe extern "C" fn line_sender_buffer_capacity(buffer: *const line_sender_ /// rows by calling `rewind_to_marker`. /// Any previous marker will be discarded. /// Once the marker is no longer needed, call `clear_marker`. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_set_marker( buffer: *mut line_sender_buffer, err_out: *mut *mut line_sender_error, ) -> bool { - let buffer = unwrap_buffer_mut(buffer); - bubble_err_to_c!(err_out, buffer.set_marker()); - true + unsafe { + let buffer = unwrap_buffer_mut(buffer); + bubble_err_to_c!(err_out, buffer.set_marker()); + true + } } /// Undo all changes since the last `set_marker` call. /// As a side-effect, this also clears the marker. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_rewind_to_marker( buffer: *mut line_sender_buffer, err_out: *mut *mut line_sender_error, ) -> bool { - let buffer = unwrap_buffer_mut(buffer); - bubble_err_to_c!(err_out, buffer.rewind_to_marker()); - true + unsafe { + let buffer = unwrap_buffer_mut(buffer); + bubble_err_to_c!(err_out, buffer.rewind_to_marker()); + true + } } /// Discard the marker. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_clear_marker(buffer: *mut line_sender_buffer) { - let buffer = unwrap_buffer_mut(buffer); - buffer.clear_marker(); + unsafe { + let buffer = unwrap_buffer_mut(buffer); + buffer.clear_marker(); + } } /// Remove all accumulated data and prepare the buffer for new lines. /// This does not affect the buffer's capacity. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_clear(buffer: *mut line_sender_buffer) { - let buffer = unwrap_buffer_mut(buffer); - buffer.clear(); + unsafe { + let buffer = unwrap_buffer_mut(buffer); + buffer.clear(); + } } /// The number of bytes accumulated in the buffer. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_size(buffer: *const line_sender_buffer) -> size_t { - let buffer = unwrap_buffer(buffer); - buffer.len() + unsafe { + let buffer = unwrap_buffer(buffer); + buffer.len() + } } /// The number of rows accumulated in the buffer. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_row_count(buffer: *const line_sender_buffer) -> size_t { - let buffer = unwrap_buffer(buffer); - buffer.row_count() + unsafe { + let buffer = unwrap_buffer(buffer); + buffer.row_count() + } } /// Tell whether the buffer is transactional. It is transactional iff it contains /// data for at most one table. Additionally, you must send the buffer over HTTP to /// get transactional behavior. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_transactional( buffer: *const line_sender_buffer, ) -> bool { - let buffer = unwrap_buffer(buffer); - buffer.transactional() + unsafe { + let buffer = unwrap_buffer(buffer); + buffer.transactional() + } } #[repr(C)] @@ -815,30 +856,34 @@ pub struct line_sender_buffer_view { /// @return A [`line_sender_buffer_view`] struct containing: /// - `buf`: Immutable pointer to the byte stream /// - `len`: Exact byte length of the data -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_peek( buffer: *const line_sender_buffer, ) -> line_sender_buffer_view { - let buffer = unwrap_buffer(buffer); - let buf: &[u8] = buffer.as_bytes(); - line_sender_buffer_view { - len: buf.len(), - buf: buf.as_ptr(), + unsafe { + let buffer = unwrap_buffer(buffer); + let buf: &[u8] = buffer.as_bytes(); + line_sender_buffer_view { + len: buf.len(), + buf: buf.as_ptr(), + } } } /// Start recording a new row for the given table. /// @param[in] buffer Line buffer object. /// @param[in] name Table name. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_table( buffer: *mut line_sender_buffer, name: line_sender_table_name, err_out: *mut *mut line_sender_error, ) -> bool { - let buffer = unwrap_buffer_mut(buffer); - bubble_err_to_c!(err_out, buffer.table(name.as_name())); - true + unsafe { + let buffer = unwrap_buffer_mut(buffer); + bubble_err_to_c!(err_out, buffer.table(name.as_name())); + true + } } /// Record a symbol value for the given column. @@ -848,16 +893,18 @@ pub unsafe extern "C" fn line_sender_buffer_table( /// @param[in] value Column value. /// @param[out] err_out Set on error. /// @return true on success, false on error. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_symbol( buffer: *mut line_sender_buffer, name: line_sender_column_name, value: line_sender_utf8, err_out: *mut *mut line_sender_error, ) -> bool { - let buffer = unwrap_buffer_mut(buffer); - bubble_err_to_c!(err_out, buffer.symbol(name.as_name(), value.as_str())); - true + unsafe { + let buffer = unwrap_buffer_mut(buffer); + bubble_err_to_c!(err_out, buffer.symbol(name.as_name(), value.as_str())); + true + } } /// Record a boolean value for the given column. @@ -866,16 +913,18 @@ pub unsafe extern "C" fn line_sender_buffer_symbol( /// @param[in] value Column value. /// @param[out] err_out Set on error. /// @return true on success, false on error. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_column_bool( buffer: *mut line_sender_buffer, name: line_sender_column_name, value: bool, err_out: *mut *mut line_sender_error, ) -> bool { - let buffer = unwrap_buffer_mut(buffer); - bubble_err_to_c!(err_out, buffer.column_bool(name.as_name(), value)); - true + unsafe { + let buffer = unwrap_buffer_mut(buffer); + bubble_err_to_c!(err_out, buffer.column_bool(name.as_name(), value)); + true + } } /// Record an integer value for the given column. @@ -884,16 +933,18 @@ pub unsafe extern "C" fn line_sender_buffer_column_bool( /// @param[in] value Column value. /// @param[out] err_out Set on error. /// @return true on success, false on error. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_column_i64( buffer: *mut line_sender_buffer, name: line_sender_column_name, value: i64, err_out: *mut *mut line_sender_error, ) -> bool { - let buffer = unwrap_buffer_mut(buffer); - bubble_err_to_c!(err_out, buffer.column_i64(name.as_name(), value)); - true + unsafe { + let buffer = unwrap_buffer_mut(buffer); + bubble_err_to_c!(err_out, buffer.column_i64(name.as_name(), value)); + true + } } /// Record a floating-point value for the given column. @@ -902,16 +953,18 @@ pub unsafe extern "C" fn line_sender_buffer_column_i64( /// @param[in] value Column value. /// @param[out] err_out Set on error. /// @return true on success, false on error. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_column_f64( buffer: *mut line_sender_buffer, name: line_sender_column_name, value: f64, err_out: *mut *mut line_sender_error, ) -> bool { - let buffer = unwrap_buffer_mut(buffer); - bubble_err_to_c!(err_out, buffer.column_f64(name.as_name(), value)); - true + unsafe { + let buffer = unwrap_buffer_mut(buffer); + bubble_err_to_c!(err_out, buffer.column_f64(name.as_name(), value)); + true + } } /// Record a string value for the given column. @@ -920,18 +973,20 @@ pub unsafe extern "C" fn line_sender_buffer_column_f64( /// @param[in] value Column value. /// @param[out] err_out Set on error. /// @return true on success, false on error. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_column_str( buffer: *mut line_sender_buffer, name: line_sender_column_name, value: line_sender_utf8, err_out: *mut *mut line_sender_error, ) -> bool { - let buffer = unwrap_buffer_mut(buffer); - let name = name.as_name(); - let value = value.as_str(); - bubble_err_to_c!(err_out, buffer.column_str(name, value)); - true + unsafe { + let buffer = unwrap_buffer_mut(buffer); + let name = name.as_name(); + let value = value.as_str(); + bubble_err_to_c!(err_out, buffer.column_str(name, value)); + true + } } /// Records a float64 multidimensional array with **C-MAJOR memory layout**. @@ -948,7 +1003,7 @@ pub unsafe extern "C" fn line_sender_buffer_column_str( /// - shape must point to an array of `rank` integers /// - data must point to a buffer of size `data_len` f64 elements. /// - QuestDB server version 9.0.0 or later is required for array support. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_column_f64_arr_c_major( buffer: *mut line_sender_buffer, name: line_sender_column_name, @@ -958,21 +1013,23 @@ pub unsafe extern "C" fn line_sender_buffer_column_f64_arr_c_major( data_len: size_t, err_out: *mut *mut line_sender_error, ) -> bool { - let buffer = unwrap_buffer_mut(buffer); - let name = name.as_name(); - let view = match CMajorArrayView::::new(rank, shape, data, data_len) { - Ok(value) => value, - Err(err) => { - let err_ptr = Box::into_raw(Box::new(line_sender_error(err))); - *err_out = err_ptr; - return false; - } - }; - bubble_err_to_c!( - err_out, - buffer.column_arr::, CMajorArrayView<'_, f64>, f64>(name, &view) - ); - true + unsafe { + let buffer = unwrap_buffer_mut(buffer); + let name = name.as_name(); + let view = match CMajorArrayView::::new(rank, shape, data, data_len) { + Ok(value) => value, + Err(err) => { + let err_ptr = Box::into_raw(Box::new(line_sender_error(err))); + *err_out = err_ptr; + return false; + } + }; + bubble_err_to_c!( + err_out, + buffer.column_arr::, CMajorArrayView<'_, f64>, f64>(name, &view) + ); + true + } } /// Records a float64 multidimensional array with **byte-level strides specification**. @@ -992,7 +1049,7 @@ pub unsafe extern "C" fn line_sender_buffer_column_f64_arr_c_major( /// - shape must point to an array of `rank` integers /// - data must point to a buffer of size `data_len` f64 elements. /// - QuestDB server version 9.0.0 or later is required for array support. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_column_f64_arr_byte_strides( buffer: *mut line_sender_buffer, name: line_sender_column_name, @@ -1003,21 +1060,23 @@ pub unsafe extern "C" fn line_sender_buffer_column_f64_arr_byte_strides( data_len: size_t, err_out: *mut *mut line_sender_error, ) -> bool { - let buffer = unwrap_buffer_mut(buffer); - let name = name.as_name(); - generate_array_dims_branches!( - rank, - 1, - shape, - strides, - data, - data_len, - err_out, - buffer, - name - => 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 - ); - true + unsafe { + let buffer = unwrap_buffer_mut(buffer); + let name = name.as_name(); + generate_array_dims_branches!( + rank, + 1, + shape, + strides, + data, + data_len, + err_out, + buffer, + name + => 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 + ); + true + } } /// Records a float64 multidimensional array with **element count stride specification**. @@ -1038,7 +1097,7 @@ pub unsafe extern "C" fn line_sender_buffer_column_f64_arr_byte_strides( /// - shape must point to an array of `rank` integers /// - data must point to a buffer of size `data_len` f64 elements. /// - QuestDB server version 9.0.0 or later is required for array support. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_column_f64_arr_elem_strides( buffer: *mut line_sender_buffer, name: line_sender_column_name, @@ -1049,21 +1108,23 @@ pub unsafe extern "C" fn line_sender_buffer_column_f64_arr_elem_strides( data_len: size_t, err_out: *mut *mut line_sender_error, ) -> bool { - let buffer = unwrap_buffer_mut(buffer); - let name = name.as_name(); - generate_array_dims_branches!( - rank, - 8, - shape, - strides, - data, - data_len, - err_out, - buffer, - name - => 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 - ); - true + unsafe { + let buffer = unwrap_buffer_mut(buffer); + let name = name.as_name(); + generate_array_dims_branches!( + rank, + 8, + shape, + strides, + data, + data_len, + err_out, + buffer, + name + => 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 + ); + true + } } /// Record a nanosecond timestamp value for the given column. @@ -1072,17 +1133,19 @@ pub unsafe extern "C" fn line_sender_buffer_column_f64_arr_elem_strides( /// @param[in] nanos The timestamp in nanoseconds before or since the unix epoch. /// @param[out] err_out Set on error. /// @return true on success, false on error. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_column_ts_nanos( buffer: *mut line_sender_buffer, name: line_sender_column_name, nanos: i64, err_out: *mut *mut line_sender_error, ) -> bool { - let buffer = unwrap_buffer_mut(buffer); - let timestamp = TimestampNanos::new(nanos); - bubble_err_to_c!(err_out, buffer.column_ts(name.as_name(), timestamp)); - true + unsafe { + let buffer = unwrap_buffer_mut(buffer); + let timestamp = TimestampNanos::new(nanos); + bubble_err_to_c!(err_out, buffer.column_ts(name.as_name(), timestamp)); + true + } } /// Record a microsecond timestamp value for the given column. @@ -1091,17 +1154,19 @@ pub unsafe extern "C" fn line_sender_buffer_column_ts_nanos( /// @param[in] micros The timestamp in microseconds before or since the unix epoch. /// @param[out] err_out Set on error. /// @return true on success, false on error. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_column_ts_micros( buffer: *mut line_sender_buffer, name: line_sender_column_name, micros: i64, err_out: *mut *mut line_sender_error, ) -> bool { - let buffer = unwrap_buffer_mut(buffer); - let timestamp = TimestampMicros::new(micros); - bubble_err_to_c!(err_out, buffer.column_ts(name.as_name(), timestamp)); - true + unsafe { + let buffer = unwrap_buffer_mut(buffer); + let timestamp = TimestampMicros::new(micros); + bubble_err_to_c!(err_out, buffer.column_ts(name.as_name(), timestamp)); + true + } } /// Complete the current row with the designated timestamp in nanoseconds. @@ -1117,16 +1182,18 @@ pub unsafe extern "C" fn line_sender_buffer_column_ts_micros( /// @param[in] epoch_nanos Number of nanoseconds since 1st Jan 1970 UTC. /// @param[out] err_out Set on error. /// @return true on success, false on error. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_at_nanos( buffer: *mut line_sender_buffer, epoch_nanos: i64, err_out: *mut *mut line_sender_error, ) -> bool { - let buffer = unwrap_buffer_mut(buffer); - let timestamp = TimestampNanos::new(epoch_nanos); - bubble_err_to_c!(err_out, buffer.at(timestamp)); - true + unsafe { + let buffer = unwrap_buffer_mut(buffer); + let timestamp = TimestampNanos::new(epoch_nanos); + bubble_err_to_c!(err_out, buffer.at(timestamp)); + true + } } /// Complete the current row with the designated timestamp in microseconds. @@ -1142,16 +1209,18 @@ pub unsafe extern "C" fn line_sender_buffer_at_nanos( /// @param[in] epoch_micros Number of microseconds since 1st Jan 1970 UTC. /// @param[out] err_out Set on error. /// @return true on success, false on error. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_at_micros( buffer: *mut line_sender_buffer, epoch_micros: i64, err_out: *mut *mut line_sender_error, ) -> bool { - let buffer = unwrap_buffer_mut(buffer); - let timestamp = TimestampMicros::new(epoch_micros); - bubble_err_to_c!(err_out, buffer.at(timestamp)); - true + unsafe { + let buffer = unwrap_buffer_mut(buffer); + let timestamp = TimestampMicros::new(epoch_micros); + bubble_err_to_c!(err_out, buffer.at(timestamp)); + true + } } /// Complete the current row without providing a timestamp. The QuestDB instance @@ -1176,14 +1245,16 @@ pub unsafe extern "C" fn line_sender_buffer_at_micros( /// @param[in] buffer Line buffer object. /// @param[out] err_out Set on error. /// @return true on success, false on error. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_at_now( buffer: *mut line_sender_buffer, err_out: *mut *mut line_sender_error, ) -> bool { - let buffer = unwrap_buffer_mut(buffer); - bubble_err_to_c!(err_out, buffer.at_now()); - true + unsafe { + let buffer = unwrap_buffer_mut(buffer); + bubble_err_to_c!(err_out, buffer.at_now()); + true + } } /** @@ -1191,14 +1262,16 @@ pub unsafe extern "C" fn line_sender_buffer_at_now( * If this returns false, the buffer is incomplete and cannot be sent, * and an error message is set to indicate the problem. */ -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_check_can_flush( buffer: *const line_sender_buffer, err_out: *mut *mut line_sender_error, ) -> bool { - let buffer = unwrap_buffer(buffer); - bubble_err_to_c!(err_out, buffer.check_can_flush()); - true + unsafe { + let buffer = unwrap_buffer(buffer); + bubble_err_to_c!(err_out, buffer.check_can_flush()); + true + } } /// Accumulates parameters for a new `line_sender` object. @@ -1218,24 +1291,28 @@ pub struct line_sender_opts(SenderBuilder); /// `line_sender_opts_new`, so there's no function with a matching name. /// /// For the full list of keys, search this module for `fn line_sender_opts_`. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_opts_from_conf( config: line_sender_utf8, err_out: *mut *mut line_sender_error, ) -> *mut line_sender_opts { - let config = config.as_str(); - let builder = bubble_err_to_c!(err_out, SenderBuilder::from_conf(config), ptr::null_mut()); - Box::into_raw(Box::new(line_sender_opts(builder))) + unsafe { + let config = config.as_str(); + let builder = bubble_err_to_c!(err_out, SenderBuilder::from_conf(config), ptr::null_mut()); + Box::into_raw(Box::new(line_sender_opts(builder))) + } } /// Create a new `line_sender_opts` instance from the configuration stored in the /// `QDB_CLIENT_CONF` environment variable. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_opts_from_env( err_out: *mut *mut line_sender_error, ) -> *mut line_sender_opts { - let builder = bubble_err_to_c!(err_out, SenderBuilder::from_env(), ptr::null_mut()); - Box::into_raw(Box::new(line_sender_opts(builder))) + unsafe { + let builder = bubble_err_to_c!(err_out, SenderBuilder::from_env(), ptr::null_mut()); + Box::into_raw(Box::new(line_sender_opts(builder))) + } } /// Create a new `line_sender_opts` instance with the given protocol, hostname and @@ -1243,7 +1320,7 @@ pub unsafe extern "C" fn line_sender_opts_from_env( /// @param[in] protocol The protocol to use. /// @param[in] host The QuestDB database host. /// @param[in] port The QuestDB ILP TCP port. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_opts_new( protocol: line_sender_protocol, host: line_sender_utf8, @@ -1258,7 +1335,7 @@ pub unsafe extern "C" fn line_sender_opts_new( /// Create a new `line_sender_opts` instance with the given protocol, hostname and /// service name. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_opts_new_service( protocol: line_sender_protocol, host: line_sender_utf8, @@ -1276,13 +1353,13 @@ pub unsafe extern "C" fn line_sender_opts_new_service( /// This may be relevant if your machine has multiple network interfaces. /// /// The default is `0.0.0.0`. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_opts_bind_interface( opts: *mut line_sender_opts, bind_interface: line_sender_utf8, err_out: *mut *mut line_sender_error, ) -> bool { - upd_opts!(opts, err_out, bind_interface, bind_interface.as_str()) + unsafe { upd_opts!(opts, err_out, bind_interface, bind_interface.as_str()) } } /// Set the username for authentication. @@ -1292,55 +1369,55 @@ pub unsafe extern "C" fn line_sender_opts_bind_interface( /// /// For HTTP, this is part of basic authentication. /// See also: `line_sender_opts_password()`. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_opts_username( opts: *mut line_sender_opts, username: line_sender_utf8, err_out: *mut *mut line_sender_error, ) -> bool { - upd_opts!(opts, err_out, username, username.as_str()) + unsafe { upd_opts!(opts, err_out, username, username.as_str()) } } /// Set the password for basic HTTP authentication. /// See also: `line_sender_opts_username()`. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_opts_password( opts: *mut line_sender_opts, password: line_sender_utf8, err_out: *mut *mut line_sender_error, ) -> bool { - upd_opts!(opts, err_out, password, password.as_str()) + unsafe { upd_opts!(opts, err_out, password, password.as_str()) } } /// Set the Token (Bearer) Authentication parameter for HTTP, /// or the ECDSA private key for TCP authentication. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_opts_token( opts: *mut line_sender_opts, token: line_sender_utf8, err_out: *mut *mut line_sender_error, ) -> bool { - upd_opts!(opts, err_out, token, token.as_str()) + unsafe { upd_opts!(opts, err_out, token, token.as_str()) } } /// Set the ECDSA public key X for TCP authentication. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_opts_token_x( opts: *mut line_sender_opts, token_x: line_sender_utf8, err_out: *mut *mut line_sender_error, ) -> bool { - upd_opts!(opts, err_out, token_x, token_x.as_str()) + unsafe { upd_opts!(opts, err_out, token_x, token_x.as_str()) } } /// Set the ECDSA public key Y for TCP authentication. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_opts_token_y( opts: *mut line_sender_opts, token_y: line_sender_utf8, err_out: *mut *mut line_sender_error, ) -> bool { - upd_opts!(opts, err_out, token_y, token_y.as_str()) + unsafe { upd_opts!(opts, err_out, token_y, token_y.as_str()) } } /// Sets the ingestion protocol version. @@ -1351,26 +1428,28 @@ pub unsafe extern "C" fn line_sender_opts_token_y( /// arrays. /// /// QuestDB server version 9.0.0 or later is required for [`ProtocolVersion::V2`] support -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_opts_protocol_version( opts: *mut line_sender_opts, version: ProtocolVersion, err_out: *mut *mut line_sender_error, ) -> bool { - upd_opts!(opts, err_out, protocol_version, version.into()) + unsafe { upd_opts!(opts, err_out, protocol_version, version.into()) } } /// Configure how long to wait for messages from the QuestDB server during /// the TLS handshake and authentication process. /// The value is in milliseconds, and the default is 15 seconds. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_opts_auth_timeout( opts: *mut line_sender_opts, timeout_millis: u64, err_out: *mut *mut line_sender_error, ) -> bool { - let timeout = std::time::Duration::from_millis(timeout_millis); - upd_opts!(opts, err_out, auth_timeout, timeout) + unsafe { + let timeout = std::time::Duration::from_millis(timeout_millis); + upd_opts!(opts, err_out, auth_timeout, timeout) + } } /// Set to `false` to disable TLS certificate verification. @@ -1378,25 +1457,27 @@ pub unsafe extern "C" fn line_sender_opts_auth_timeout( /// /// For testing consider specifying a path to a `.pem` file instead via /// the `tls_roots` setting. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_opts_tls_verify( opts: *mut line_sender_opts, verify: bool, err_out: *mut *mut line_sender_error, ) -> bool { - upd_opts!(opts, err_out, tls_verify, verify) + unsafe { upd_opts!(opts, err_out, tls_verify, verify) } } /// Specify where to find the certificate authority used to validate /// the validate the server's TLS certificate. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_opts_tls_ca( opts: *mut line_sender_opts, ca: line_sender_ca, err_out: *mut *mut line_sender_error, ) -> bool { - let ca: CertificateAuthority = ca.into(); - upd_opts!(opts, err_out, tls_ca, ca) + unsafe { + let ca: CertificateAuthority = ca.into(); + upd_opts!(opts, err_out, tls_ca, ca) + } } /// Set the path to a custom root certificate `.pem` file. @@ -1404,48 +1485,52 @@ pub unsafe extern "C" fn line_sender_opts_tls_ca( /// /// See notes on how to test with [self-signed /// certificates](https://github.com/questdb/c-questdb-client/tree/main/tls_certs). -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_opts_tls_roots( opts: *mut line_sender_opts, path: line_sender_utf8, err_out: *mut *mut line_sender_error, ) -> bool { - let path = PathBuf::from(path.as_str()); - upd_opts!(opts, err_out, tls_roots, path) + unsafe { + let path = PathBuf::from(path.as_str()); + upd_opts!(opts, err_out, tls_roots, path) + } } /// Set the maximum buffer size in bytes that the client will flush to the server. /// The default is 100 MiB. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_opts_max_buf_size( opts: *mut line_sender_opts, max_buf_size: size_t, err_out: *mut *mut line_sender_error, ) -> bool { - upd_opts!(opts, err_out, max_buf_size, max_buf_size) + unsafe { upd_opts!(opts, err_out, max_buf_size, max_buf_size) } } /// Ser the maximum length of a table or column name in bytes. /// The default is 127 bytes. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_opts_max_name_len( opts: *mut line_sender_opts, max_name_len: size_t, err_out: *mut *mut line_sender_error, ) -> bool { - upd_opts!(opts, err_out, max_name_len, max_name_len) + unsafe { upd_opts!(opts, err_out, max_name_len, max_name_len) } } /// Set the cumulative duration spent in retries. /// The value is in milliseconds, and the default is 10 seconds. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_opts_retry_timeout( opts: *mut line_sender_opts, millis: u64, err_out: *mut *mut line_sender_error, ) -> bool { - let retry_timeout = std::time::Duration::from_millis(millis); - upd_opts!(opts, err_out, retry_timeout, retry_timeout) + unsafe { + let retry_timeout = std::time::Duration::from_millis(millis); + upd_opts!(opts, err_out, retry_timeout, retry_timeout) + } } /// Set the minimum acceptable throughput while sending a buffer to the server. @@ -1456,13 +1541,13 @@ pub unsafe extern "C" fn line_sender_opts_retry_timeout( /// `request_timeout`. /// /// See also: `line_sender_opts_request_timeout()` -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_opts_request_min_throughput( opts: *mut line_sender_opts, bytes_per_sec: u64, err_out: *mut *mut line_sender_error, ) -> bool { - upd_opts!(opts, err_out, request_min_throughput, bytes_per_sec) + unsafe { upd_opts!(opts, err_out, request_min_throughput, bytes_per_sec) } } /// Set the additional time to wait on top of that calculated from the minimum @@ -1470,43 +1555,49 @@ pub unsafe extern "C" fn line_sender_opts_request_min_throughput( /// roundtrip. The value is in milliseconds, and the default is 10 seconds. /// /// See also: `line_sender_opts_request_min_throughput()` -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_opts_request_timeout( opts: *mut line_sender_opts, millis: u64, err_out: *mut *mut line_sender_error, ) -> bool { - let request_timeout = std::time::Duration::from_millis(millis); - upd_opts!(opts, err_out, request_timeout, request_timeout) + unsafe { + let request_timeout = std::time::Duration::from_millis(millis); + upd_opts!(opts, err_out, request_timeout, request_timeout) + } } /// Set the HTTP user agent. Internal API. Do not use. #[doc(hidden)] -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_opts_user_agent( opts: *mut line_sender_opts, user_agent: line_sender_utf8, err_out: *mut *mut line_sender_error, ) -> bool { - upd_opts!(opts, err_out, user_agent, user_agent.as_str()) + unsafe { upd_opts!(opts, err_out, user_agent, user_agent.as_str()) } } /// Duplicate the `line_sender_opts` object. /// Both old and new objects will have to be freed. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_opts_clone( opts: *const line_sender_opts, ) -> *mut line_sender_opts { - let builder = &(*opts).0; - let new_builder = builder.clone(); - Box::into_raw(Box::new(line_sender_opts(new_builder))) + unsafe { + let builder = &(*opts).0; + let new_builder = builder.clone(); + Box::into_raw(Box::new(line_sender_opts(new_builder))) + } } /// Release the `line_sender_opts` object. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_opts_free(opts: *mut line_sender_opts) { - if !opts.is_null() { - drop(Box::from_raw(opts)); + unsafe { + if !opts.is_null() { + drop(Box::from_raw(opts)); + } } } @@ -1526,14 +1617,16 @@ pub struct line_sender(Sender); /// The sender should be accessed by only a single thread a time. /// /// @param[in] opts Options for the connection. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_build( opts: *const line_sender_opts, err_out: *mut *mut line_sender_error, ) -> *mut line_sender { - let builder = &(*opts).0; - let sender = bubble_err_to_c!(err_out, builder.build(), ptr::null_mut()); - Box::into_raw(Box::new(line_sender(sender))) + unsafe { + let builder = &(*opts).0; + let sender = bubble_err_to_c!(err_out, builder.build(), ptr::null_mut()); + Box::into_raw(Box::new(line_sender(sender))) + } } /// Create a new line sender instance from the given configuration string. @@ -1557,18 +1650,20 @@ pub unsafe extern "C" fn line_sender_build( /// returning. /// /// The sender should be accessed by only a single thread a time. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_from_conf( config: line_sender_utf8, err_out: *mut *mut line_sender_error, ) -> *mut line_sender { - let config = config.as_str(); - let builder = bubble_err_to_c!(err_out, SenderBuilder::from_conf(config), ptr::null_mut()); - let builder = builder - .user_agent(concat!("questdb/c/", env!("CARGO_PKG_VERSION"))) - .expect("user_agent set"); - let sender = bubble_err_to_c!(err_out, builder.build(), ptr::null_mut()); - Box::into_raw(Box::new(line_sender(sender))) + unsafe { + let config = config.as_str(); + let builder = bubble_err_to_c!(err_out, SenderBuilder::from_conf(config), ptr::null_mut()); + let builder = builder + .user_agent(concat!("questdb/c/", env!("CARGO_PKG_VERSION"))) + .expect("user_agent set"); + let sender = bubble_err_to_c!(err_out, builder.build(), ptr::null_mut()); + Box::into_raw(Box::new(line_sender(sender))) + } } /// Create a new `line_sender` instance from the configuration stored in the @@ -1580,24 +1675,26 @@ pub unsafe extern "C" fn line_sender_from_conf( /// returning. /// /// The sender should be accessed by only a single thread a time. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_from_env( err_out: *mut *mut line_sender_error, ) -> *mut line_sender { - let builder = bubble_err_to_c!(err_out, SenderBuilder::from_env(), ptr::null_mut()); - let builder = builder - .user_agent(concat!("questdb/c/", env!("CARGO_PKG_VERSION"))) - .expect("user_agent set"); - let sender = bubble_err_to_c!(err_out, builder.build(), ptr::null_mut()); - Box::into_raw(Box::new(line_sender(sender))) + unsafe { + let builder = bubble_err_to_c!(err_out, SenderBuilder::from_env(), ptr::null_mut()); + let builder = builder + .user_agent(concat!("questdb/c/", env!("CARGO_PKG_VERSION"))) + .expect("user_agent set"); + let sender = bubble_err_to_c!(err_out, builder.build(), ptr::null_mut()); + Box::into_raw(Box::new(line_sender(sender))) + } } unsafe fn unwrap_sender<'a>(sender: *const line_sender) -> &'a Sender { - &(*sender).0 + unsafe { &(*sender).0 } } unsafe fn unwrap_sender_mut<'a>(sender: *mut line_sender) -> &'a mut Sender { - &mut (*sender).0 + unsafe { &mut (*sender).0 } } /// Returns the sender's protocol version @@ -1605,26 +1702,28 @@ unsafe fn unwrap_sender_mut<'a>(sender: *mut line_sender) -> &'a mut Sender { /// - Explicitly set version, or /// - Auto-detected during HTTP transport, or /// - [`ProtocolVersion::V1`] for TCP transport. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_get_protocol_version( sender: *const line_sender, ) -> ProtocolVersion { - unwrap_sender(sender).protocol_version().into() + unsafe { unwrap_sender(sender).protocol_version().into() } } -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_get_max_name_len(sender: *const line_sender) -> size_t { - unwrap_sender(sender).max_name_len() + unsafe { unwrap_sender(sender).max_name_len() } } /// Construct a [`line_sender_buffer`] using the sender's protocol settings. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_buffer_new_for_sender( sender: *const line_sender, ) -> *mut line_sender_buffer { - let sender = unwrap_sender(sender); - let buffer = sender.new_buffer(); - Box::into_raw(Box::new(line_sender_buffer(buffer))) + unsafe { + let sender = unwrap_sender(sender); + let buffer = sender.new_buffer(); + Box::into_raw(Box::new(line_sender_buffer(buffer))) + } } /// Tell whether the sender is no longer usable and must be closed. @@ -1632,17 +1731,19 @@ pub unsafe extern "C" fn line_sender_buffer_new_for_sender( /// This fuction is specific to TCP and is not relevant for HTTP. /// @param[in] sender Line sender object. /// @return true if an error occurred with a sender and it must be closed. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_must_close(sender: *const line_sender) -> bool { - unwrap_sender(sender).must_close() + unsafe { unwrap_sender(sender).must_close() } } /// Close the connection. Does not flush. Non-idempotent. /// @param[in] sender Line sender object. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_close(sender: *mut line_sender) { - if !sender.is_null() { - drop(Box::from_raw(sender)); + unsafe { + if !sender.is_null() { + drop(Box::from_raw(sender)); + } } } @@ -1672,16 +1773,18 @@ pub unsafe extern "C" fn line_sender_close(sender: *mut line_sender) { /// @param[in] sender Line sender object. /// @param[in] buffer Line buffer object. /// @return true on success, false on error. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_flush( sender: *mut line_sender, buffer: *mut line_sender_buffer, err_out: *mut *mut line_sender_error, ) -> bool { - let sender = unwrap_sender_mut(sender); - let buffer = unwrap_buffer_mut(buffer); - bubble_err_to_c!(err_out, sender.flush(buffer)); - true + unsafe { + let sender = unwrap_sender_mut(sender); + let buffer = unwrap_buffer_mut(buffer); + bubble_err_to_c!(err_out, sender.flush(buffer)); + true + } } /// Send the given buffer of rows to the QuestDB server. @@ -1693,16 +1796,18 @@ pub unsafe extern "C" fn line_sender_flush( /// @param[in] sender Line sender object. /// @param[in] buffer Line buffer object. /// @return true on success, false on error. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_flush_and_keep( sender: *mut line_sender, buffer: *const line_sender_buffer, err_out: *mut *mut line_sender_error, ) -> bool { - let sender = unwrap_sender_mut(sender); - let buffer = unwrap_buffer(buffer); - bubble_err_to_c!(err_out, sender.flush_and_keep(buffer)); - true + unsafe { + let sender = unwrap_sender_mut(sender); + let buffer = unwrap_buffer(buffer); + bubble_err_to_c!(err_out, sender.flush_and_keep(buffer)); + true + } } /// Send the batch of rows in the buffer to the QuestDB server, and, if the parameter @@ -1721,30 +1826,32 @@ pub unsafe extern "C" fn line_sender_flush_and_keep( /// error, it retries until it has exhausted the retry time budget. /// /// All the data stays in the buffer. Clear the buffer before starting a new batch. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_flush_and_keep_with_flags( sender: *mut line_sender, buffer: *const line_sender_buffer, transactional: bool, err_out: *mut *mut line_sender_error, ) -> bool { - let sender = unwrap_sender_mut(sender); - let buffer = unwrap_buffer(buffer); - bubble_err_to_c!( - err_out, - sender.flush_and_keep_with_flags(buffer, transactional) - ); - true + unsafe { + let sender = unwrap_sender_mut(sender); + let buffer = unwrap_buffer(buffer); + bubble_err_to_c!( + err_out, + sender.flush_and_keep_with_flags(buffer, transactional) + ); + true + } } /// Get the current time in nanoseconds since the Unix epoch (UTC). -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_now_nanos() -> i64 { TimestampNanos::now().as_i64() } /// Get the current time in microseconds since the Unix epoch (UTC). -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn line_sender_now_micros() -> i64 { TimestampMicros::now().as_i64() } @@ -1759,6 +1866,8 @@ use questdb_confstr_ffi::questdb_conf_str_parse_err; /// included in the final binary. /// This is because otherwise `cargo` will optimise out the dependency. pub unsafe fn _build_system_hack(err: *mut questdb_conf_str_parse_err) { - use questdb_confstr_ffi::questdb_conf_str_parse_err_free; - questdb_conf_str_parse_err_free(err); + unsafe { + use questdb_confstr_ffi::questdb_conf_str_parse_err_free; + questdb_conf_str_parse_err_free(err); + } } diff --git a/questdb-rs-ffi/src/ndarr.rs b/questdb-rs-ffi/src/ndarr.rs index f8e5ec57..10a113b0 100644 --- a/questdb-rs-ffi/src/ndarr.rs +++ b/questdb-rs-ffi/src/ndarr.rs @@ -23,10 +23,10 @@ ******************************************************************************/ use crate::fmt_error; +use questdb::Error; use questdb::ingress::ArrayElement; -use questdb::ingress::NdArrayView; use questdb::ingress::MAX_ARRAY_BUFFER_SIZE; -use questdb::Error; +use questdb::ingress::NdArrayView; use std::mem::size_of; use std::slice; @@ -112,18 +112,20 @@ where data: *const T, len: usize, ) -> Result { - let shape = check_array_shape::(D, shape, len)?; - let strides = slice::from_raw_parts(strides, D); - let mut slice = None; - if len != 0 { - slice = Some(slice::from_raw_parts(data, len)); + unsafe { + let shape = check_array_shape::(D, shape, len)?; + let strides = slice::from_raw_parts(strides, D); + let mut slice = None; + if len != 0 { + slice = Some(slice::from_raw_parts(data, len)); + } + Ok(Self { + shape, + strides, + data: slice, + _marker: std::marker::PhantomData::, + }) } - Ok(Self { - shape, - strides, - data: slice, - _marker: std::marker::PhantomData::, - }) } /// Verifies if the array follows C-style row-major memory layout. @@ -329,17 +331,19 @@ where data: *const T, data_len: usize, ) -> Result { - let shape = check_array_shape::(dims, shape, data_len)?; - let mut slice = None; - if data_len != 0 { - slice = Some(slice::from_raw_parts(data, data_len)); + unsafe { + let shape = check_array_shape::(dims, shape, data_len)?; + let mut slice = None; + if data_len != 0 { + slice = Some(slice::from_raw_parts(data, data_len)); + } + Ok(Self { + dims, + shape, + data: slice, + _marker: std::marker::PhantomData::, + }) } - Ok(Self { - dims, - shape, - data: slice, - _marker: std::marker::PhantomData::, - }) } } @@ -581,9 +585,10 @@ mod tests { }; let err = result.unwrap_err(); assert_eq!(err.code(), ErrorCode::ArrayError); - assert!(err - .msg() - .contains("Array element length mismatch (actual: 1, expected: 2)")); + assert!( + err.msg() + .contains("Array element length mismatch (actual: 1, expected: 2)") + ); let over_data = [1.1, 2.2, 3.3]; let result: Result, Error> = unsafe { @@ -597,9 +602,10 @@ mod tests { let err = result.unwrap_err(); assert_eq!(err.code(), ErrorCode::ArrayError); - assert!(err - .msg() - .contains("Array element length mismatch (actual: 3, expected: 2)")); + assert!( + err.msg() + .contains("Array element length mismatch (actual: 3, expected: 2)") + ); Ok(()) } @@ -617,9 +623,10 @@ mod tests { }; let err = result.unwrap_err(); assert_eq!(err.code(), ErrorCode::ArrayError); - assert!(err - .msg() - .contains("Array element length mismatch (actual: 1, expected: 2)")); + assert!( + err.msg() + .contains("Array element length mismatch (actual: 1, expected: 2)") + ); let over_data = [1.1, 2.2, 3.3]; let result: Result, Error> = unsafe { @@ -633,9 +640,10 @@ mod tests { let err = result.unwrap_err(); assert_eq!(err.code(), ErrorCode::ArrayError); - assert!(err - .msg() - .contains("Array element length mismatch (actual: 3, expected: 2)")); + assert!( + err.msg() + .contains("Array element length mismatch (actual: 3, expected: 2)") + ); Ok(()) } diff --git a/questdb-rs/Cargo.toml b/questdb-rs/Cargo.toml index 5212488b..96e6ce86 100644 --- a/questdb-rs/Cargo.toml +++ b/questdb-rs/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "questdb-rs" version = "5.1.0" -edition = "2021" +edition = "2024" license = "Apache-2.0" description = "QuestDB Client Library for Rust" -homepage = "https://questdb.io/" +homepage = "https://questdb.com/" repository = "https://github.com/questdb/c-questdb-client" keywords = ["questdb", "ilp", "client-library"] categories = ["database"] @@ -19,23 +19,22 @@ crate-type = ["lib"] [dependencies] libc = "0.2" -socket2 = { version = "0.5.5", optional = true } -dns-lookup = "2.0.4" +socket2 = { version = "0.6.1", optional = true } +dns-lookup = "3.0.0" base64ct = { version = "1.7", features = ["alloc"] } -rustls-pemfile = "2.0.0" ryu = { version = "1.0" } itoa = "1.0" aws-lc-rs = { version = "1.13", optional = true } ring = { version = "0.17.14", optional = true } -rustls-pki-types = "1.0.1" +rustls-pki-types = "1.12.0" rustls = { version = "0.23.25", default-features = false, features = ["logging", "std", "tls12"] } -rustls-native-certs = { version = "0.8.1", optional = true } -webpki-roots = { version = "1.0.1", default-features = false, optional = true } +rustls-native-certs = { version = "0.8.2", optional = true } +webpki-roots = { version = "1.0.3", default-features = false, optional = true } chrono = { version = "0.4.40", optional = true } # We need to limit the `ureq` version to 3.0.x since we use # the `ureq::unversioned` module which does not respect semantic versioning. -ureq = { version = "3.0.10, <3.1.0", default-features = false, features = ["_tls"], optional = true } +ureq = { version = "3.1.2, <3.2.0", default-features = false, optional = true } serde_json = { version = "1", optional = true } questdb-confstr = "0.1.1" rand = { version = "0.9.0", optional = true } @@ -51,12 +50,12 @@ slugify = "0.1.0" indoc = "2" [dev-dependencies] -socket2 = "0.5.5" +socket2 = "0.6.1" mio = { version = "1", features = ["os-poll", "net"] } chrono = "0.4.31" tempfile = "3" webpki-roots = "1.0.1" -rstest = "0.25.0" +rstest = "0.26.1" [features] default = ["sync-sender", "tls-webpki-certs", "ring-crypto"] diff --git a/questdb-rs/build.rs b/questdb-rs/build.rs index df2d3000..20aa6529 100644 --- a/questdb-rs/build.rs +++ b/questdb-rs/build.rs @@ -278,10 +278,14 @@ fn main() -> Result<(), Box> { ); #[cfg(not(any(feature = "aws-lc-crypto", feature = "ring-crypto")))] - compile_error!("You must enable exactly one of the `aws-lc-crypto` or `ring-crypto` features, but none are enabled."); + compile_error!( + "You must enable exactly one of the `aws-lc-crypto` or `ring-crypto` features, but none are enabled." + ); #[cfg(all(feature = "aws-lc-crypto", feature = "ring-crypto"))] - compile_error!("You must enable exactly one of the `aws-lc-crypto` or `ring-crypto` features, but both are enabled."); + compile_error!( + "You must enable exactly one of the `aws-lc-crypto` or `ring-crypto` features, but both are enabled." + ); #[cfg(feature = "json_tests")] { diff --git a/questdb-rs/examples/auth.rs b/questdb-rs/examples/auth.rs index 10eb20be..1b638f0e 100644 --- a/questdb-rs/examples/auth.rs +++ b/questdb-rs/examples/auth.rs @@ -1,7 +1,7 @@ use chrono::{TimeZone, Utc}; use questdb::{ - ingress::{Sender, TimestampNanos}, Result, + ingress::{Sender, TimestampNanos}, }; fn main() -> Result<()> { diff --git a/questdb-rs/examples/auth_tls.rs b/questdb-rs/examples/auth_tls.rs index 8355ebd5..f9ddb218 100644 --- a/questdb-rs/examples/auth_tls.rs +++ b/questdb-rs/examples/auth_tls.rs @@ -1,7 +1,7 @@ use chrono::{TimeZone, Utc}; use questdb::{ - ingress::{Sender, TimestampNanos}, Result, + ingress::{Sender, TimestampNanos}, }; fn main() -> Result<()> { diff --git a/questdb-rs/examples/basic.rs b/questdb-rs/examples/basic.rs index 05c1f7c9..22155c39 100644 --- a/questdb-rs/examples/basic.rs +++ b/questdb-rs/examples/basic.rs @@ -1,8 +1,8 @@ use chrono::{TimeZone, Utc}; use ndarray::arr1; use questdb::{ - ingress::{Sender, TimestampNanos}, Result, + ingress::{Sender, TimestampNanos}, }; fn main() -> Result<()> { diff --git a/questdb-rs/examples/from_conf.rs b/questdb-rs/examples/from_conf.rs index 2cdbaed0..5daa7fd2 100644 --- a/questdb-rs/examples/from_conf.rs +++ b/questdb-rs/examples/from_conf.rs @@ -1,6 +1,6 @@ use questdb::{ - ingress::{Sender, TimestampNanos}, Result, + ingress::{Sender, TimestampNanos}, }; fn main() -> Result<()> { diff --git a/questdb-rs/examples/from_env.rs b/questdb-rs/examples/from_env.rs index 8b2b3d8b..9687f567 100644 --- a/questdb-rs/examples/from_env.rs +++ b/questdb-rs/examples/from_env.rs @@ -1,6 +1,6 @@ use questdb::{ - ingress::{Sender, TimestampNanos}, Result, + ingress::{Sender, TimestampNanos}, }; fn main() -> Result<()> { diff --git a/questdb-rs/examples/http.rs b/questdb-rs/examples/http.rs index a3f4e8d7..9895be49 100644 --- a/questdb-rs/examples/http.rs +++ b/questdb-rs/examples/http.rs @@ -1,7 +1,7 @@ use ndarray::arr1; use questdb::{ - ingress::{Sender, TimestampNanos}, Result, + ingress::{Sender, TimestampNanos}, }; fn main() -> Result<()> { diff --git a/questdb-rs/examples/protocol_version.rs b/questdb-rs/examples/protocol_version.rs index e78fe6a6..840b4e2e 100644 --- a/questdb-rs/examples/protocol_version.rs +++ b/questdb-rs/examples/protocol_version.rs @@ -1,7 +1,7 @@ use ndarray::arr1; use questdb::{ - ingress::{Sender, TimestampNanos}, Result, + ingress::{Sender, TimestampNanos}, }; fn main() -> Result<()> { diff --git a/questdb-rs/src/ingress/buffer.rs b/questdb-rs/src/ingress/buffer.rs index b87688bf..4ed554b8 100644 --- a/questdb-rs/src/ingress/buffer.rs +++ b/questdb-rs/src/ingress/buffer.rs @@ -21,13 +21,13 @@ * limitations under the License. * ******************************************************************************/ -use crate::ingress::ndarr::{check_and_get_array_bytes_size, ArrayElementSealed}; +use crate::ingress::ndarr::{ArrayElementSealed, check_and_get_array_bytes_size}; use crate::ingress::{ - ndarr, ArrayElement, DebugBytes, NdArrayView, ProtocolVersion, Timestamp, TimestampMicros, - TimestampNanos, ARRAY_BINARY_FORMAT_TYPE, DOUBLE_BINARY_FORMAT_TYPE, MAX_ARRAY_DIMS, - MAX_NAME_LEN_DEFAULT, + ARRAY_BINARY_FORMAT_TYPE, ArrayElement, DOUBLE_BINARY_FORMAT_TYPE, DebugBytes, MAX_ARRAY_DIMS, + MAX_NAME_LEN_DEFAULT, NdArrayView, ProtocolVersion, Timestamp, TimestampMicros, TimestampNanos, + ndarr, }; -use crate::{error, Error}; +use crate::{Error, error}; use std::fmt::{Debug, Formatter}; use std::num::NonZeroUsize; use std::slice::from_raw_parts_mut; diff --git a/questdb-rs/src/ingress/mod.rs b/questdb-rs/src/ingress/mod.rs index 052774bc..ad4938a9 100644 --- a/questdb-rs/src/ingress/mod.rs +++ b/questdb-rs/src/ingress/mod.rs @@ -26,7 +26,7 @@ pub use self::ndarr::{ArrayElement, NdArrayView}; pub use self::timestamp::*; -use crate::error::{self, fmt, Result}; +use crate::error::{self, Result, fmt}; use crate::ingress::conf::ConfigSetting; use core::time::Duration; use std::collections::HashMap; @@ -41,13 +41,13 @@ mod tls; #[cfg(all(feature = "_sender-tcp", feature = "aws-lc-crypto"))] use aws_lc_rs::{ rand::SystemRandom, - signature::{EcdsaKeyPair, ECDSA_P256_SHA256_FIXED_SIGNING}, + signature::{ECDSA_P256_SHA256_FIXED_SIGNING, EcdsaKeyPair}, }; #[cfg(all(feature = "_sender-tcp", feature = "ring-crypto"))] use ring::{ rand::SystemRandom, - signature::{EcdsaKeyPair, ECDSA_P256_SHA256_FIXED_SIGNING}, + signature::{ECDSA_P256_SHA256_FIXED_SIGNING, EcdsaKeyPair}, }; mod conf; @@ -162,14 +162,14 @@ impl From for Port { } fn validate_auto_flush_params(params: &HashMap) -> Result<()> { - if let Some(auto_flush) = params.get("auto_flush") { - if auto_flush.as_str() != "off" { - return Err(error::fmt!( - ConfigError, - "Invalid auto_flush value '{auto_flush}'. This client does not \ - support auto-flush, so the only accepted value is 'off'" - )); - } + if let Some(auto_flush) = params.get("auto_flush") + && auto_flush.as_str() != "off" + { + return Err(error::fmt!( + ConfigError, + "Invalid auto_flush value '{auto_flush}'. This client does not \ + support auto-flush, so the only accepted value is 'off'" + )); } for ¶m in ["auto_flush_rows", "auto_flush_bytes"].iter() { @@ -422,18 +422,16 @@ impl SenderBuilder { return Err(error::fmt!( ConfigError, "invalid \"protocol_version\" [value={invalid}, allowed-values=[auto, 1, 2]]]\"]" - )) + )); } }, - "max_name_len" => { - builder.max_name_len(parse_conf_value(key, val)?)? - } + "max_name_len" => builder.max_name_len(parse_conf_value(key, val)?)?, "init_buf_size" => { return Err(error::fmt!( ConfigError, "\"init_buf_size\" is not supported in config string" - )) + )); } "max_buf_size" => builder.max_buf_size(parse_conf_value(key, val)?)?, @@ -450,7 +448,7 @@ impl SenderBuilder { return Err(fmt!( ConfigError, r##"Config parameter "tls_verify" must be either "on" or "unsafe_off".'"##, - )) + )); } }; @@ -475,21 +473,44 @@ impl SenderBuilder { "webpki_roots" => CertificateAuthority::WebpkiRoots, #[cfg(not(feature = "tls-webpki-certs"))] - "webpki_roots" => return Err(error::fmt!(ConfigError, "Config parameter \"tls_ca=webpki_roots\" requires the \"tls-webpki-certs\" feature")), + "webpki_roots" => { + return Err(error::fmt!( + ConfigError, + "Config parameter \"tls_ca=webpki_roots\" requires the \"tls-webpki-certs\" feature" + )); + } #[cfg(feature = "tls-native-certs")] "os_roots" => CertificateAuthority::OsRoots, #[cfg(not(feature = "tls-native-certs"))] - "os_roots" => return Err(error::fmt!(ConfigError, "Config parameter \"tls_ca=os_roots\" requires the \"tls-native-certs\" feature")), + "os_roots" => { + return Err(error::fmt!( + ConfigError, + "Config parameter \"tls_ca=os_roots\" requires the \"tls-native-certs\" feature" + )); + } #[cfg(all(feature = "tls-webpki-certs", feature = "tls-native-certs"))] "webpki_and_os_roots" => CertificateAuthority::WebpkiAndOsRoots, - #[cfg(not(all(feature = "tls-webpki-certs", feature = "tls-native-certs")))] - "webpki_and_os_roots" => return Err(error::fmt!(ConfigError, "Config parameter \"tls_ca=webpki_and_os_roots\" requires both the \"tls-webpki-certs\" and \"tls-native-certs\" features")), + #[cfg(not(all( + feature = "tls-webpki-certs", + feature = "tls-native-certs" + )))] + "webpki_and_os_roots" => { + return Err(error::fmt!( + ConfigError, + "Config parameter \"tls_ca=webpki_and_os_roots\" requires both the \"tls-webpki-certs\" and \"tls-native-certs\" features" + )); + } - _ => return Err(error::fmt!(ConfigError, "Invalid value {val:?} for \"tls_ca\"")), + _ => { + return Err(error::fmt!( + ConfigError, + "Invalid value {val:?} for \"tls_ca\"" + )); + } }; builder.tls_ca(ca)? } @@ -510,7 +531,7 @@ impl SenderBuilder { return Err(error::fmt!( ConfigError, "\"tls_roots_password\" is not supported." - )) + )); } #[cfg(feature = "sync-sender-http")] @@ -902,109 +923,101 @@ impl SenderBuilder { self.username.deref(), self.password.deref(), self.token.deref(), - #[cfg(feature = "_sender-tcp")] self.token_x.deref(), - #[cfg(not(feature = "_sender-tcp"))] None::, - #[cfg(feature = "_sender-tcp")] self.token_y.deref(), - #[cfg(not(feature = "_sender-tcp"))] None::, ) { (_, None, None, None, None, None) => Ok(None), #[cfg(feature = "_sender-tcp")] - ( - protocol, - Some(username), - None, - Some(token), - Some(token_x), - Some(token_y), - ) if protocol.is_tcpx() => Ok(Some(conf::AuthParams::Ecdsa(conf::EcdsaAuthParams { - key_id: username.to_string(), - priv_key: token.to_string(), - pub_key_x: token_x.to_string(), - pub_key_y: token_y.to_string(), - }))), + (protocol, Some(username), None, Some(token), Some(token_x), Some(token_y)) + if protocol.is_tcpx() => + { + Ok(Some(conf::AuthParams::Ecdsa(conf::EcdsaAuthParams { + key_id: username.to_string(), + priv_key: token.to_string(), + pub_key_x: token_x.to_string(), + pub_key_y: token_y.to_string(), + }))) + } #[cfg(feature = "_sender-tcp")] (protocol, Some(_username), Some(_password), None, None, None) - if protocol.is_tcpx() => { - Err(error::fmt!(ConfigError, + if protocol.is_tcpx() => + { + Err(error::fmt!( + ConfigError, r##"The "basic_auth" setting can only be used with the ILP/HTTP protocol."##, )) } #[cfg(feature = "_sender-tcp")] - (protocol, None, None, Some(_token), None, None) - if protocol.is_tcpx() => { - Err(error::fmt!(ConfigError, "Token authentication only be used with the ILP/HTTP protocol.")) + (protocol, None, None, Some(_token), None, None) if protocol.is_tcpx() => { + Err(error::fmt!( + ConfigError, + "Token authentication only be used with the ILP/HTTP protocol." + )) } #[cfg(feature = "_sender-tcp")] - (protocol, _username, None, _token, _token_x, _token_y) - if protocol.is_tcpx() => { - Err(error::fmt!(ConfigError, + (protocol, _username, None, _token, _token_x, _token_y) if protocol.is_tcpx() => { + Err(error::fmt!( + ConfigError, r##"Incomplete ECDSA authentication parameters. Specify either all or none of: "username", "token", "token_x", "token_y"."##, )) } #[cfg(feature = "_sender-http")] - (protocol, Some(username), Some(password), None, None, None) - if protocol.is_httpx() => { + (protocol, Some(username), Some(password), None, None, None) if protocol.is_httpx() => { Ok(Some(conf::AuthParams::Basic(conf::BasicAuthParams { username: username.to_string(), password: password.to_string(), }))) } #[cfg(feature = "_sender-http")] - (protocol, Some(_username), None, None, None, None) - if protocol.is_httpx() => { - Err(error::fmt!(ConfigError, + (protocol, Some(_username), None, None, None, None) if protocol.is_httpx() => { + Err(error::fmt!( + ConfigError, r##"Basic authentication parameter "username" is present, but "password" is missing."##, )) } #[cfg(feature = "_sender-http")] - (protocol, None, Some(_password), None, None, None) - if protocol.is_httpx() => { - Err(error::fmt!(ConfigError, + (protocol, None, Some(_password), None, None, None) if protocol.is_httpx() => { + Err(error::fmt!( + ConfigError, r##"Basic authentication parameter "password" is present, but "username" is missing."##, )) } #[cfg(feature = "sync-sender-http")] - (protocol, None, None, Some(token), None, None) - if protocol.is_httpx() => { + (protocol, None, None, Some(token), None, None) if protocol.is_httpx() => { Ok(Some(conf::AuthParams::Token(conf::TokenAuthParams { token: token.to_string(), }))) } #[cfg(feature = "sync-sender-http")] - ( - protocol, - Some(_username), - None, - Some(_token), - Some(_token_x), - Some(_token_y), - ) if protocol.is_httpx() => { - Err(error::fmt!(ConfigError, "ECDSA authentication is only available with ILP/TCP and not available with ILP/HTTP.")) + (protocol, Some(_username), None, Some(_token), Some(_token_x), Some(_token_y)) + if protocol.is_httpx() => + { + Err(error::fmt!( + ConfigError, + "ECDSA authentication is only available with ILP/TCP and not available with ILP/HTTP." + )) } #[cfg(feature = "_sender-http")] - (protocol, _username, _password, _token, None, None) - if protocol.is_httpx() => { - Err(error::fmt!(ConfigError, + (protocol, _username, _password, _token, None, None) if protocol.is_httpx() => { + Err(error::fmt!( + ConfigError, r##"Inconsistent HTTP authentication parameters. Specify either "username" and "password", or just "token"."##, )) } - _ => { - Err(error::fmt!(ConfigError, - r##"Incomplete authentication parameters. Check "username", "password", "token", "token_x" and "token_y" parameters are set correctly."##, - )) - } + _ => Err(error::fmt!( + ConfigError, + r##"Incomplete authentication parameters. Check "username", "password", "token", "token_x" and "token_y" parameters are set correctly."##, + )), } } diff --git a/questdb-rs/src/ingress/ndarr.rs b/questdb-rs/src/ingress/ndarr.rs index 0a1374c0..247119dc 100644 --- a/questdb-rs/src/ingress/ndarr.rs +++ b/questdb-rs/src/ingress/ndarr.rs @@ -177,11 +177,11 @@ impl NdArrayView for Vec { Ok(self.len()) } else { Err(error::fmt!( - ArrayError, - "Dimension index out of bounds. Requested axis {}, but array only has {} dimension(s)", - idx, - 1 - )) + ArrayError, + "Dimension index out of bounds. Requested axis {}, but array only has {} dimension(s)", + idx, + 1 + )) } } @@ -210,11 +210,11 @@ impl NdArrayView for [T; N] { Ok(N) } else { Err(error::fmt!( - ArrayError, - "Dimension index out of bounds. Requested axis {}, but array only has {} dimension(s)", - idx, - 1 - )) + ArrayError, + "Dimension index out of bounds. Requested axis {}, but array only has {} dimension(s)", + idx, + 1 + )) } } @@ -244,11 +244,11 @@ impl NdArrayView for &[T] { Ok(self.len()) } else { Err(error::fmt!( - ArrayError, - "Dimension index out of bounds. Requested axis {}, but array only has {} dimension(s)", - idx, - 1 - )) + ArrayError, + "Dimension index out of bounds. Requested axis {}, but array only has {} dimension(s)", + idx, + 1 + )) } } @@ -283,11 +283,11 @@ impl NdArrayView for Vec> { Ok(dim1) } _ => Err(error::fmt!( - ArrayError, - "Dimension index out of bounds. Requested axis {}, but array only has {} dimension(s)", - idx, - 2 - )), + ArrayError, + "Dimension index out of bounds. Requested axis {}, but array only has {} dimension(s)", + idx, + 2 + )), } } @@ -316,11 +316,11 @@ impl NdArrayView for [[T; M] 0 => Ok(N), 1 => Ok(M), _ => Err(error::fmt!( - ArrayError, - "Dimension index out of bounds. Requested axis {}, but array only has {} dimension(s)", - idx, - 2 - )), + ArrayError, + "Dimension index out of bounds. Requested axis {}, but array only has {} dimension(s)", + idx, + 2 + )), } } @@ -350,11 +350,11 @@ impl NdArrayView for &[[T; M]] { 0 => Ok(self.len()), 1 => Ok(M), _ => Err(error::fmt!( - ArrayError, - "Dimension index out of bounds. Requested axis {}, but array only has {} dimension(s)", - idx, - 2 - )), + ArrayError, + "Dimension index out of bounds. Requested axis {}, but array only has {} dimension(s)", + idx, + 2 + )), } } @@ -405,11 +405,11 @@ impl NdArrayView for Vec>> { Ok(dim2) } _ => Err(error::fmt!( - ArrayError, - "Dimension index out of bounds. Requested axis {}, but array only has {} dimension(s)", - idx, - 3 - )), + ArrayError, + "Dimension index out of bounds. Requested axis {}, but array only has {} dimension(s)", + idx, + 3 + )), } } @@ -441,11 +441,11 @@ impl NdArrayVie 1 => Ok(N), 2 => Ok(M), _ => Err(error::fmt!( - ArrayError, - "Dimension index out of bounds. Requested axis {}, but array only has {} dimension(s)", - idx, - 3 - )), + ArrayError, + "Dimension index out of bounds. Requested axis {}, but array only has {} dimension(s)", + idx, + 3 + )), } } @@ -475,11 +475,11 @@ impl NdArrayView for &[[[T; 1 => Ok(N), 2 => Ok(M), _ => Err(error::fmt!( - ArrayError, - "Dimension index out of bounds. Requested axis {}, but array only has {} dimension(s)", - idx, - 3 - )), + ArrayError, + "Dimension index out of bounds. Requested axis {}, but array only has {} dimension(s)", + idx, + 3 + )), } } @@ -492,7 +492,7 @@ impl NdArrayView for &[[[T; } } -use crate::{error, Error}; +use crate::{Error, error}; #[cfg(feature = "ndarray")] use ndarray::{ArrayView, Axis, Dimension}; use std::slice; @@ -521,11 +521,11 @@ where Ok(self.len_of(Axis(index))) } else { Err(error::fmt!( - ArrayError, - "Dimension index out of bounds. Requested axis {}, but array only has {} dimension(s)", - index, - 3 - )) + ArrayError, + "Dimension index out of bounds. Requested axis {}, but array only has {} dimension(s)", + index, + 3 + )) } } diff --git a/questdb-rs/src/ingress/sender/http.rs b/questdb-rs/src/ingress/sender/http.rs index 3a99be8e..fa34cc74 100644 --- a/questdb-rs/src/ingress/sender/http.rs +++ b/questdb-rs/src/ingress/sender/http.rs @@ -23,7 +23,7 @@ ******************************************************************************/ use crate::error::fmt; -use crate::{error, Error}; +use crate::{Error, error}; use rand::Rng; use rustls::{ClientConnection, StreamOwned}; use rustls_pki_types::ServerName; @@ -38,10 +38,10 @@ use ureq::unversioned::transport::{ Buffers, Connector, LazyBuffers, NextTimeout, Transport, TransportAdapter, }; -use crate::ingress::conf::HttpConfig; use crate::ingress::ProtocolVersion; +use crate::ingress::conf::HttpConfig; use ureq::unversioned::*; -use ureq::{http, Body}; +use ureq::{Body, http}; #[cfg(feature = "sync-sender-http")] pub(crate) struct SyncHttpHandlerState { @@ -320,7 +320,7 @@ pub(super) fn parse_http_error(http_status_code: u16, response: Response) } }; - if let Some(serde_json::Value::String(ref msg)) = json.get("message") { + if let Some(serde_json::Value::String(msg)) = json.get("message") { parse_json_error(&json, msg) } else { string_err() @@ -457,7 +457,7 @@ pub(crate) fn read_server_settings( })?; let mut support_versions: Vec = vec![]; - if let Some(serde_json::Value::Array(ref values)) = json + if let Some(serde_json::Value::Array(values)) = json .get("config") .and_then(|v| v.get("line.proto.support.versions")) { @@ -483,7 +483,8 @@ pub(crate) fn read_server_settings( } else { Err(error::fmt!( ProtocolVersionError, - "Malformed server response, settings url: {}, err: failed to read response body as UTF-8", settings_url + "Malformed server response, settings url: {}, err: failed to read response body as UTF-8", + settings_url )) } } diff --git a/questdb-rs/src/ingress/sender/tcp.rs b/questdb-rs/src/ingress/sender/tcp.rs index e9a2e91e..907e67aa 100644 --- a/questdb-rs/src/ingress/sender/tcp.rs +++ b/questdb-rs/src/ingress/sender/tcp.rs @@ -24,8 +24,8 @@ use crate::error; use crate::gai; -use crate::ingress::tls::{configure_tls, TlsSettings}; -use crate::ingress::{conf, map_io_to_socket_err, parse_key_pair, SyncProtocolHandler}; +use crate::ingress::tls::{TlsSettings, configure_tls}; +use crate::ingress::{SyncProtocolHandler, conf, map_io_to_socket_err, parse_key_pair}; use rustls::{ClientConnection, StreamOwned}; use rustls_pki_types::ServerName; use socket2::{Domain, Protocol as SockProtocol, SockAddr, Socket, Type}; @@ -143,6 +143,7 @@ impl IoWrite for SyncConnection { // We also set SO_LINGER to 120, but that is not enough apparently. impl Drop for SyncProtocolHandler { fn drop(&mut self) { + #[allow(irrefutable_let_patterns)] // HTTP feature might be disabled. if let SyncProtocolHandler::SyncTcp(conn) = self { match conn { SyncConnection::Direct(sock) => { @@ -178,7 +179,7 @@ pub(crate) fn connect_tcp( .map_err(|io_err| map_io_to_socket_err("Could not set socket linger: ", io_err))?; sock.set_keepalive(true) .map_err(|io_err| map_io_to_socket_err("Could not set SO_KEEPALIVE: ", io_err))?; - sock.set_nodelay(true) + sock.set_tcp_nodelay(true) .map_err(|io_err| map_io_to_socket_err("Could not set TCP_NODELAY: ", io_err))?; if let Some(host) = net_interface { let bind_addr = gai::resolve_host(host)?; diff --git a/questdb-rs/src/ingress/tests.rs b/questdb-rs/src/ingress/tests.rs index d4e40a8f..a2cb9bcc 100644 --- a/questdb-rs/src/ingress/tests.rs +++ b/questdb-rs/src/ingress/tests.rs @@ -361,7 +361,7 @@ fn incomplete_tcp_ecdsa_auth() { fn misspelled_tcp_ecdsa_auth() { assert_conf_err( Sender::from_conf("tcp::addr=localhost;username=user123;tokenx=123;"), - "Incomplete ECDSA authentication parameters. Specify either all or none of: \"username\", \"token\", \"token_x\", \"token_y\"." + "Incomplete ECDSA authentication parameters. Specify either all or none of: \"username\", \"token\", \"token_x\", \"token_y\".", ); } @@ -453,9 +453,10 @@ fn tcps_tls_roots_file_missing() { SenderBuilder::from_conf("tcps::addr=localhost;tls_roots=/some/invalid/path/cacerts.pem;") .unwrap_err(); assert_eq!(err.code(), ErrorCode::ConfigError); - assert!(err - .msg() - .contains("Could not open root certificate file from path")); + assert!( + err.msg() + .contains("Could not open root certificate file from path") + ); } #[cfg(feature = "sync-sender-tcp")] diff --git a/questdb-rs/src/ingress/tls.rs b/questdb-rs/src/ingress/tls.rs index 85a84fd9..354ea364 100644 --- a/questdb-rs/src/ingress/tls.rs +++ b/questdb-rs/src/ingress/tls.rs @@ -1,9 +1,9 @@ -use crate::error::{fmt, Result}; +use crate::error::{Result, fmt}; use crate::ingress::CertificateAuthority; use rustls::RootCertStore; use rustls_pki_types::CertificateDer; +use rustls_pki_types::pem::PemObject; use std::fs::File; -use std::io::BufReader; use std::path::Path; use std::sync::Arc; @@ -144,7 +144,10 @@ impl TlsSettings { #[cfg(feature = "tls-webpki-certs")] (CertificateAuthority::WebpkiRoots, Some(_)) => { - return Err(fmt!(ConfigError, "Config parameter \"tls_roots\" must be unset when \"tls_ca\" is set to \"webpki_roots\".")); + return Err(fmt!( + ConfigError, + "Config parameter \"tls_roots\" must be unset when \"tls_ca\" is set to \"webpki_roots\"." + )); } #[cfg(feature = "tls-native-certs")] @@ -152,7 +155,10 @@ impl TlsSettings { #[cfg(feature = "tls-native-certs")] (CertificateAuthority::OsRoots, Some(_)) => { - return Err(fmt!(ConfigError, "Config parameter \"tls_roots\" must be unset when \"tls_ca\" is set to \"os_roots\".")); + return Err(fmt!( + ConfigError, + "Config parameter \"tls_roots\" must be unset when \"tls_ca\" is set to \"os_roots\"." + )); } #[cfg(all(feature = "tls-webpki-certs", feature = "tls-native-certs"))] @@ -160,11 +166,17 @@ impl TlsSettings { #[cfg(all(feature = "tls-webpki-certs", feature = "tls-native-certs"))] (CertificateAuthority::WebpkiAndOsRoots, Some(_)) => { - return Err(fmt!(ConfigError, "Config parameter \"tls_roots\" must be unset when \"tls_ca\" is set to \"webpki_and_os_roots\".")); + return Err(fmt!( + ConfigError, + "Config parameter \"tls_roots\" must be unset when \"tls_ca\" is set to \"webpki_and_os_roots\"." + )); } (CertificateAuthority::PemFile, None) => { - return Err(fmt!(ConfigError, "Config parameter \"tls_roots\" is required when \"tls_ca\" is set to \"pem_file\".")); + return Err(fmt!( + ConfigError, + "Config parameter \"tls_roots\" is required when \"tls_ca\" is set to \"pem_file\"." + )); } (CertificateAuthority::PemFile, Some(pem_file)) => { @@ -179,8 +191,8 @@ impl TlsSettings { io_err ) })?; - let mut reader = BufReader::new(certfile); - let der_certs = rustls_pemfile::certs(&mut reader) + + let der_certs = CertificateDer::pem_reader_iter(certfile) .collect::, _>>() .map_err(|io_err| { fmt!( diff --git a/questdb-rs/src/tests/http.rs b/questdb-rs/src/tests/http.rs index d19b9f09..7055fd0c 100644 --- a/questdb-rs/src/tests/http.rs +++ b/questdb-rs/src/tests/http.rs @@ -22,10 +22,10 @@ * ******************************************************************************/ -use crate::ingress::{Buffer, Protocol, ProtocolVersion, SenderBuilder, TimestampNanos}; -use crate::tests::mock::{certs_dir, HttpResponse, MockServer}; -use crate::tests::{assert_err_contains, TestResult}; use crate::ErrorCode; +use crate::ingress::{Buffer, Protocol, ProtocolVersion, SenderBuilder, TimestampNanos}; +use crate::tests::mock::{HttpResponse, MockServer, certs_dir}; +use crate::tests::{TestResult, assert_err_contains}; use rstest::rstest; use std::io; use std::io::ErrorKind; @@ -231,9 +231,11 @@ fn test_no_connection( assert!(res.is_err()); let err = res.unwrap_err(); assert_eq!(err.code(), ErrorCode::SocketError); - assert!(err - .msg() - .starts_with("Could not flush buffer: http://127.0.0.1:1/write: io: Connection refused")); + assert!( + err.msg().starts_with( + "Could not flush buffer: http://127.0.0.1:1/write: io: Connection refused" + ) + ); Ok(()) } diff --git a/questdb-rs/src/tests/mock.rs b/questdb-rs/src/tests/mock.rs index 91880fb4..b1dab709 100644 --- a/questdb-rs/src/tests/mock.rs +++ b/questdb-rs/src/tests/mock.rs @@ -28,10 +28,12 @@ use core::time::Duration; use mio::event::Event; use mio::net::TcpStream; use mio::{Events, Interest, Poll, Token}; -use rustls::{server::ServerConnection, ServerConfig, Stream}; +use rustls::{ServerConfig, Stream, server::ServerConnection}; +use rustls_pki_types::pem::PemObject; +use rustls_pki_types::{CertificateDer, PrivateKeyDer}; use socket2::{Domain, Protocol as SockProtocol, Socket, Type}; use std::fs::File; -use std::io::{self, BufReader, Read}; +use std::io::{self, Read}; use std::net::SocketAddr; use std::sync::Arc; use std::time::Instant; @@ -70,16 +72,14 @@ pub fn certs_dir() -> std::path::PathBuf { fn tls_config() -> Arc { let certs_dir = certs_dir(); - let mut cert_file = - File::open(certs_dir.join("server.crt")).expect("cannot open certificate file"); - let mut private_key_file = + let cert_file = File::open(certs_dir.join("server.crt")).expect("cannot open certificate file"); + let private_key_file = File::open(certs_dir.join("server.key")).expect("cannot open private key file"); - let certs = rustls_pemfile::certs(&mut BufReader::new(&mut cert_file)) + let certs = CertificateDer::pem_reader_iter(cert_file) .collect::, _>>() .expect("cannot read certificate file"); - let private_key = rustls_pemfile::private_key(&mut BufReader::new(&mut private_key_file)) - .expect("cannot read private key file") - .expect("no private key found"); + let private_key = + PrivateKeyDer::from_pem_reader(private_key_file).expect("cannot get private key from file"); let config = ServerConfig::builder() .with_no_client_auth() .with_single_cert(certs, private_key) diff --git a/questdb-rs/src/tests/ndarr.rs b/questdb-rs/src/tests/ndarr.rs index b43f0437..18cd7e84 100644 --- a/questdb-rs/src/tests/ndarr.rs +++ b/questdb-rs/src/tests/ndarr.rs @@ -22,16 +22,16 @@ * ******************************************************************************/ -use crate::ingress::{Buffer, NdArrayView, ProtocolVersion, ARRAY_BINARY_FORMAT_TYPE}; -use crate::tests::TestResult; use crate::ErrorCode; +use crate::ingress::{ARRAY_BINARY_FORMAT_TYPE, Buffer, NdArrayView, ProtocolVersion}; +use crate::tests::TestResult; -#[cfg(feature = "ndarray")] -use crate::ingress::ndarr::write_array_data; #[cfg(feature = "ndarray")] use crate::ingress::MAX_ARRAY_DIMS; #[cfg(feature = "ndarray")] -use ndarray::{arr1, arr2, arr3, s, ArrayD}; +use crate::ingress::ndarr::write_array_data; +#[cfg(feature = "ndarray")] +use ndarray::{ArrayD, arr1, arr2, arr3, s}; #[cfg(feature = "ndarray")] use std::iter; @@ -599,7 +599,9 @@ fn test_build_in_3d_vec_normal() -> TestResult { let collected: Vec<_> = NdArrayView::iter(&vec).copied().collect(); assert_eq!( collected, - vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0] + vec![ + 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 + ] ); let mut buffer = Buffer::new(ProtocolVersion::V2); diff --git a/questdb-rs/src/tests/sender.rs b/questdb-rs/src/tests/sender.rs index 4f63b2ed..6ff41acd 100644 --- a/questdb-rs/src/tests/sender.rs +++ b/questdb-rs/src/tests/sender.rs @@ -23,11 +23,11 @@ ******************************************************************************/ use crate::{ + ErrorCode, ingress::{ - Buffer, F64Serializer, Sender, TableName, Timestamp, TimestampMicros, TimestampNanos, - DOUBLE_BINARY_FORMAT_TYPE, + Buffer, DOUBLE_BINARY_FORMAT_TYPE, F64Serializer, Sender, TableName, Timestamp, + TimestampMicros, TimestampNanos, }, - ErrorCode, }; use crate::ingress::ProtocolVersion; @@ -38,12 +38,12 @@ use core::time::Duration; use crate::ingress::ndarr::write_array_data; #[cfg(feature = "ndarray")] -use ndarray::{arr2, ArrayD}; +use ndarray::{ArrayD, arr2}; #[cfg(feature = "sync-sender-tcp")] use crate::tests::{ assert_err_contains, - mock::{certs_dir, MockServer}, + mock::{MockServer, certs_dir}, ndarr::ArrayColumnTypeTag, }; @@ -51,7 +51,7 @@ use crate::tests::{ use rstest::rstest; #[cfg(feature = "sync-sender-tcp")] -use crate::ingress::{CertificateAuthority, ARRAY_BINARY_FORMAT_TYPE}; +use crate::ingress::{ARRAY_BINARY_FORMAT_TYPE, CertificateAuthority}; #[cfg(feature = "sync-sender-tcp")] #[rstest] @@ -399,10 +399,11 @@ fn test_transactional() -> TestResult { #[cfg(feature = "sync-sender-tcp")] #[test] fn test_auth_inconsistent_keys() -> TestResult { - test_bad_key("fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU", // d - "fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU", // x - "Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac", - "Misconfigured ILP authentication keys: InconsistentComponents. Hint: Check the keys for a possible typo." + test_bad_key( + "fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU", // d + "fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU", // x + "Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac", + "Misconfigured ILP authentication keys: InconsistentComponents. Hint: Check the keys for a possible typo.", ) } @@ -413,14 +414,14 @@ fn test_auth_bad_base64_private_key() -> TestResult { "bad key", // d "fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU", // x "Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac", // y - "Misconfigured ILP authentication keys. Could not decode private authentication key: invalid Base64 encoding. Hint: Check the keys for a possible typo." + "Misconfigured ILP authentication keys. Could not decode private authentication key: invalid Base64 encoding. Hint: Check the keys for a possible typo.", ) } #[cfg(feature = "sync-sender-tcp")] #[test] fn test_auth_private_key_too_long() -> TestResult { - #[cfg(feature = "aws-lc-crypto")] + #[cfg(feature = "aws-lc-crypto")] let expected = "Misconfigured ILP authentication keys: InvalidEncoding. Hint: Check the keys for a possible typo."; #[cfg(feature = "ring-crypto")] @@ -430,7 +431,7 @@ fn test_auth_private_key_too_long() -> TestResult { "ZkxLWUVhb0ViOWxybjNua3dMREEtTV94bnVGT2RTdDl5MFo3X3ZXU0hMVWZMS1lFYW9FYjlscm4zbmt3TERBLU1feG51Rk9kU3Q5eTBaN192V1NITFU", "fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU", // x "Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac", // y - expected + expected, ) } @@ -441,7 +442,7 @@ fn test_auth_public_key_x_too_long() -> TestResult { "fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU", "ZkxLWUVhb0ViOWxybjNua3dMREEtTV94bnVGT2RTdDl5MFo3X3ZXU0hMVWZMS1lFYW9FYjlscm4zbmt3TERBLU1feG51Rk9kU3Q5eTBaN192V1NITFU", // x "Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac", // y - "Misconfigured ILP authentication keys. Public key x is too long. Hint: Check the keys for a possible typo." + "Misconfigured ILP authentication keys. Public key x is too long. Hint: Check the keys for a possible typo.", ) } @@ -452,7 +453,7 @@ fn test_auth_public_key_y_too_long() -> TestResult { "fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU", "Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac", // x "ZkxLWUVhb0ViOWxybjNua3dMREEtTV94bnVGT2RTdDl5MFo3X3ZXU0hMVWZMS1lFYW9FYjlscm4zbmt3TERBLU1feG51Rk9kU3Q5eTBaN192V1NITFU", // y - "Misconfigured ILP authentication keys. Public key y is too long. Hint: Check the keys for a possible typo." + "Misconfigured ILP authentication keys. Public key y is too long. Hint: Check the keys for a possible typo.", ) } @@ -461,9 +462,9 @@ fn test_auth_public_key_y_too_long() -> TestResult { fn test_auth_bad_base64_public_key_x() -> TestResult { test_bad_key( "fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU", // d - "bad base64 encoding", // x + "bad base64 encoding", // x "Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac", // y - "Misconfigured ILP authentication keys. Could not decode public key x: invalid Base64 encoding. Hint: Check the keys for a possible typo." + "Misconfigured ILP authentication keys. Could not decode public key x: invalid Base64 encoding. Hint: Check the keys for a possible typo.", ) } @@ -473,8 +474,8 @@ fn test_auth_bad_base64_public_key_y() -> TestResult { test_bad_key( "fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU", // d "Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac", // x - "bad base64 encoding", // y - "Misconfigured ILP authentication keys. Could not decode public key y: invalid Base64 encoding. Hint: Check the keys for a possible typo." + "bad base64 encoding", // y + "Misconfigured ILP authentication keys. Could not decode public key y: invalid Base64 encoding. Hint: Check the keys for a possible typo.", ) } diff --git a/system_test/test.py b/system_test/test.py index e60562c7..f5d263ca 100755 --- a/system_test/test.py +++ b/system_test/test.py @@ -121,16 +121,18 @@ def _ns_to_qdb_date(self, at_ts_ns, exp_nanos: bool): @property def client_driven_nanos_supported(self) -> bool: - """True if the QuestDB server supports nanos and also respects the client's precision for the designated timestamp.""" - if QDB_FIXTURE.version <= (9, 1, 0): - return False - - if QDB_FIXTURE.http: - return QDB_FIXTURE.protocol_version != qls.ProtocolVersion.V1 - elif QDB_FIXTURE.protocol_version is None: - return False # TCP defaults to ProtocolVersion.V1 - else: - return QDB_FIXTURE.protocol_version >= qls.ProtocolVersion.V2 + return False + ### Re-enable once https://github.com/questdb/questdb/pull/6220 is merged. + # """True if the QuestDB server supports nanos and also respects the client's precision for the designated timestamp.""" + # if QDB_FIXTURE.version <= (9, 1, 0): + # return False + + # if QDB_FIXTURE.http: + # return QDB_FIXTURE.protocol_version != qls.ProtocolVersion.V1 + # elif QDB_FIXTURE.protocol_version is None: + # return False # TCP defaults to ProtocolVersion.V1 + # else: + # return QDB_FIXTURE.protocol_version >= qls.ProtocolVersion.V2 @property def expected_protocol_version(self) -> qls.ProtocolVersion: