1#![allow(clippy::len_without_is_empty)]
2
3use std::ops::Deref;
4
5pub use byteorder::LittleEndian as Endianness;
6
7mod bitset;
8pub mod bounds;
9mod byte_count;
10mod datetime;
11pub mod file_slice;
12mod group_by;
13pub mod json_path_writer;
14mod serialize;
15mod vint;
16mod writer;
17pub use bitset::*;
18pub use byte_count::ByteCount;
19pub use datetime::{DateTime, DateTimePrecision};
20pub use group_by::GroupByIteratorExtended;
21pub use json_path_writer::JsonPathWriter;
22pub use ownedbytes::{OwnedBytes, StableDeref};
23pub use serialize::{BinarySerializable, DeserializeFrom, FixedSize};
24pub use vint::{
25 VInt, VIntU128, read_u32_vint, read_u32_vint_no_advance, serialize_vint_u32, write_u32_vint,
26};
27pub use writer::{AntiCallToken, CountingWriter, TerminatingWrite};
28
29pub trait HasLen {
31 fn len(&self) -> usize;
33
34 fn is_empty(&self) -> bool {
36 self.len() == 0
37 }
38}
39
40impl<T: Deref<Target = [u8]>> HasLen for T {
41 fn len(&self) -> usize {
42 self.deref().len()
43 }
44}
45
46const HIGHEST_BIT: u64 = 1 << 63;
47
48#[inline]
69pub fn i64_to_u64(val: i64) -> u64 {
70 (val as u64) ^ HIGHEST_BIT
71}
72
73#[inline]
75pub fn u64_to_i64(val: u64) -> i64 {
76 (val ^ HIGHEST_BIT) as i64
77}
78
79#[inline]
97pub fn f64_to_u64(val: f64) -> u64 {
98 let bits = val.to_bits();
99 if val.is_sign_positive() {
100 bits ^ HIGHEST_BIT
101 } else {
102 !bits
103 }
104}
105
106#[inline]
108pub fn u64_to_f64(val: u64) -> f64 {
109 f64::from_bits(if val & HIGHEST_BIT != 0 {
110 val ^ HIGHEST_BIT
111 } else {
112 !val
113 })
114}
115
116#[inline]
121pub fn replace_in_place(needle: u8, replacement: u8, bytes: &mut [u8]) {
122 if !bytes.contains(&needle) {
123 return;
124 }
125 for b in bytes {
126 if *b == needle {
127 *b = replacement;
128 }
129 }
130}
131
132#[cfg(test)]
133pub(crate) mod test {
134
135 use proptest::prelude::*;
136
137 use super::{f64_to_u64, i64_to_u64, u64_to_f64, u64_to_i64};
138
139 fn test_i64_converter_helper(val: i64) {
140 assert_eq!(u64_to_i64(i64_to_u64(val)), val);
141 }
142
143 fn test_f64_converter_helper(val: f64) {
144 assert_eq!(u64_to_f64(f64_to_u64(val)), val);
145 }
146
147 proptest! {
148 #[test]
149 fn test_f64_converter_monotonicity_proptest((left, right) in (proptest::num::f64::NORMAL, proptest::num::f64::NORMAL)) {
150 let left_u64 = f64_to_u64(left);
151 let right_u64 = f64_to_u64(right);
152 assert_eq!(left_u64 < right_u64, left < right);
153 }
154 }
155
156 #[test]
157 fn test_i64_converter() {
158 assert_eq!(i64_to_u64(i64::MIN), u64::MIN);
159 assert_eq!(i64_to_u64(i64::MAX), u64::MAX);
160 test_i64_converter_helper(0i64);
161 test_i64_converter_helper(i64::MIN);
162 test_i64_converter_helper(i64::MAX);
163 for i in -1000i64..1000i64 {
164 test_i64_converter_helper(i);
165 }
166 }
167
168 #[test]
169 fn test_f64_converter() {
170 test_f64_converter_helper(f64::INFINITY);
171 test_f64_converter_helper(f64::NEG_INFINITY);
172 test_f64_converter_helper(0.0);
173 test_f64_converter_helper(-0.0);
174 test_f64_converter_helper(1.0);
175 test_f64_converter_helper(-1.0);
176 }
177
178 #[test]
179 fn test_f64_order() {
180 assert!(
181 !(f64_to_u64(f64::NEG_INFINITY)..f64_to_u64(f64::INFINITY))
182 .contains(&f64_to_u64(f64::NAN))
183 ); assert!(f64_to_u64(1.5) > f64_to_u64(1.0)); assert!(f64_to_u64(2.0) > f64_to_u64(1.0)); assert!(f64_to_u64(2.0) > f64_to_u64(1.5)); assert!(f64_to_u64(1.0) > f64_to_u64(-1.0)); assert!(f64_to_u64(-1.5) < f64_to_u64(-1.0));
189 assert!(f64_to_u64(-2.0) < f64_to_u64(1.0));
190 assert!(f64_to_u64(-2.0) < f64_to_u64(-1.5));
191 }
192
193 #[test]
194 fn test_replace_in_place() {
195 let test_aux = |before_replacement: &[u8], expected: &[u8]| {
196 let mut bytes: Vec<u8> = before_replacement.to_vec();
197 super::replace_in_place(b'b', b'c', &mut bytes);
198 assert_eq!(&bytes[..], expected);
199 };
200 test_aux(b"", b"");
201 test_aux(b"b", b"c");
202 test_aux(b"baaa", b"caaa");
203 test_aux(b"aaab", b"aaac");
204 test_aux(b"aaabaa", b"aaacaa");
205 test_aux(b"aaaaaa", b"aaaaaa");
206 test_aux(b"bbbb", b"cccc");
207 }
208}