quack-ruby 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/LICENSE-DuckDB +7 -0
  4. data/LICENSE-QuackProtocol +21 -0
  5. data/LICENSE-Rust-dependencies.json +2057 -0
  6. data/README.md +229 -0
  7. data/ext/quack/Cargo.lock +1803 -0
  8. data/ext/quack/Cargo.toml +17 -0
  9. data/ext/quack/extconf.rb +4 -0
  10. data/ext/quack/src/lib.rs +647 -0
  11. data/ext/quack/vendor/quack_protocol/Cargo.lock +1907 -0
  12. data/ext/quack/vendor/quack_protocol/Cargo.toml +41 -0
  13. data/ext/quack/vendor/quack_protocol/LICENSE +21 -0
  14. data/ext/quack/vendor/quack_protocol/PATCHES.md +16 -0
  15. data/ext/quack/vendor/quack_protocol/README.md +272 -0
  16. data/ext/quack/vendor/quack_protocol/src/arrow/columns.rs +399 -0
  17. data/ext/quack/vendor/quack_protocol/src/arrow/mod.rs +134 -0
  18. data/ext/quack/vendor/quack_protocol/src/arrow/schema.rs +103 -0
  19. data/ext/quack/vendor/quack_protocol/src/arrow/tests.rs +851 -0
  20. data/ext/quack/vendor/quack_protocol/src/arrow/values.rs +150 -0
  21. data/ext/quack/vendor/quack_protocol/src/binary.rs +504 -0
  22. data/ext/quack/vendor/quack_protocol/src/builders.rs +217 -0
  23. data/ext/quack/vendor/quack_protocol/src/client.rs +1486 -0
  24. data/ext/quack/vendor/quack_protocol/src/constants.rs +11 -0
  25. data/ext/quack/vendor/quack_protocol/src/errors.rs +103 -0
  26. data/ext/quack/vendor/quack_protocol/src/inspection.rs +250 -0
  27. data/ext/quack/vendor/quack_protocol/src/json.rs +225 -0
  28. data/ext/quack/vendor/quack_protocol/src/lib.rs +54 -0
  29. data/ext/quack/vendor/quack_protocol/src/logical_types.rs +977 -0
  30. data/ext/quack/vendor/quack_protocol/src/messages.rs +843 -0
  31. data/ext/quack/vendor/quack_protocol/src/pool.rs +741 -0
  32. data/ext/quack/vendor/quack_protocol/src/protocol_tests.rs +759 -0
  33. data/ext/quack/vendor/quack_protocol/src/proxy_error.rs +77 -0
  34. data/ext/quack/vendor/quack_protocol/src/sql.rs +359 -0
  35. data/ext/quack/vendor/quack_protocol/src/tls.rs +354 -0
  36. data/ext/quack/vendor/quack_protocol/src/values.rs +77 -0
  37. data/ext/quack/vendor/quack_protocol/src/vector.rs +1364 -0
  38. data/ext/quack/vendor/quack_protocol/testdata/tls/key.der +0 -0
  39. data/ext/quack/vendor/quack_protocol/testdata/tls/spki.der +0 -0
  40. data/ext/quack/vendor/quack_protocol/testdata/tls/v1-cert.der +0 -0
  41. data/ext/quack/vendor/quack_protocol/testdata/tls/v3-cert.der +0 -0
  42. data/lib/quack/codec.rb +263 -0
  43. data/lib/quack/connection.rb +131 -0
  44. data/lib/quack/logical_types.rb +72 -0
  45. data/lib/quack/result.rb +64 -0
  46. data/lib/quack/sql.rb +183 -0
  47. data/lib/quack/types.rb +40 -0
  48. data/lib/quack/variant.rb +298 -0
  49. data/lib/quack.rb +34 -0
  50. metadata +136 -0
@@ -0,0 +1,150 @@
1
+ //! Extractors from a decoded `Value` to the native Arrow representation.
2
+
3
+ use arrow_array::temporal_conversions::{MICROSECONDS_IN_DAY, NANOSECONDS_IN_DAY};
4
+ use arrow_buffer::{IntervalMonthDayNano, i256};
5
+
6
+ use crate::errors::{QuackError, Result};
7
+ use crate::logical_types::LogicalTypeId;
8
+ use crate::vector::{DecimalValue, TimeUnit, TimestampUnit, Value};
9
+
10
+ use super::{mismatch, out_of_range};
11
+
12
+ const NANOS_PER_MICRO: i64 = 1_000;
13
+
14
+ pub(super) fn as_bool(id: LogicalTypeId, value: &Value) -> Result<bool> {
15
+ match value {
16
+ Value::Bool(value) => Ok(*value),
17
+ other => Err(mismatch(id, other)),
18
+ }
19
+ }
20
+
21
+ pub(super) fn as_int(id: LogicalTypeId, value: &Value) -> Result<i64> {
22
+ match value {
23
+ Value::Int(value) => Ok(*value),
24
+ other => Err(mismatch(id, other)),
25
+ }
26
+ }
27
+
28
+ pub(super) fn as_uint(id: LogicalTypeId, value: &Value) -> Result<u64> {
29
+ match value {
30
+ Value::UInt(value) => Ok(*value),
31
+ other => Err(mismatch(id, other)),
32
+ }
33
+ }
34
+
35
+ pub(super) fn as_huge_int(id: LogicalTypeId, value: &Value) -> Result<i256> {
36
+ match value {
37
+ Value::HugeInt(value) => Ok(i256::from_i128(*value)),
38
+ other => Err(mismatch(id, other)),
39
+ }
40
+ }
41
+
42
+ pub(super) fn as_unsigned_huge_int(id: LogicalTypeId, value: &Value) -> Result<i256> {
43
+ match value {
44
+ Value::UHugeInt(value) => Ok(i256::from_parts(*value, 0)),
45
+ other => Err(mismatch(id, other)),
46
+ }
47
+ }
48
+
49
+ pub(super) fn as_float(id: LogicalTypeId, value: &Value) -> Result<f32> {
50
+ match value {
51
+ Value::Float(value) => Ok(*value),
52
+ other => Err(mismatch(id, other)),
53
+ }
54
+ }
55
+
56
+ pub(super) fn as_double(id: LogicalTypeId, value: &Value) -> Result<f64> {
57
+ match value {
58
+ Value::Double(value) => Ok(*value),
59
+ other => Err(mismatch(id, other)),
60
+ }
61
+ }
62
+
63
+ pub(super) fn as_decimal(id: LogicalTypeId, value: &Value) -> Result<&DecimalValue> {
64
+ match value {
65
+ Value::Decimal(value) => Ok(value),
66
+ other => Err(mismatch(id, other)),
67
+ }
68
+ }
69
+
70
+ pub(super) fn as_str(id: LogicalTypeId, value: &Value) -> Result<&str> {
71
+ match value {
72
+ Value::String(value) => Ok(value.as_str()),
73
+ other => Err(mismatch(id, other)),
74
+ }
75
+ }
76
+
77
+ pub(super) fn as_bytes(id: LogicalTypeId, value: &Value) -> Result<&[u8]> {
78
+ match value {
79
+ Value::Bytes(value) => Ok(value.as_slice()),
80
+ other => Err(mismatch(id, other)),
81
+ }
82
+ }
83
+
84
+ pub(super) fn as_date(id: LogicalTypeId, value: &Value) -> Result<i32> {
85
+ match value {
86
+ Value::Date(value) => Ok(value.days),
87
+ other => Err(mismatch(id, other)),
88
+ }
89
+ }
90
+
91
+ pub(super) fn narrow_int<T: TryFrom<i64>>(id: LogicalTypeId, value: &Value) -> Result<T> {
92
+ let value = as_int(id, value)?;
93
+ T::try_from(value).map_err(|_| out_of_range(id, value))
94
+ }
95
+
96
+ pub(super) fn narrow_uint<T: TryFrom<u64>>(id: LogicalTypeId, value: &Value) -> Result<T> {
97
+ let value = as_uint(id, value)?;
98
+ T::try_from(value).map_err(|_| out_of_range(id, value))
99
+ }
100
+
101
+ pub(super) fn as_time(id: LogicalTypeId, value: &Value, unit: TimeUnit) -> Result<i64> {
102
+ match value {
103
+ Value::Time(value) if value.unit == unit => {
104
+ // DuckDB accepts TIME '24:00:00', which Arrow's "elapsed time since
105
+ // midnight" bound excludes.
106
+ let limit = match unit {
107
+ TimeUnit::Micros => MICROSECONDS_IN_DAY,
108
+ TimeUnit::Nanos => NANOSECONDS_IN_DAY,
109
+ };
110
+ if !(0..limit).contains(&value.value) {
111
+ return Err(out_of_range(id, value.value));
112
+ }
113
+ Ok(value.value)
114
+ }
115
+ other => Err(mismatch(id, other)),
116
+ }
117
+ }
118
+
119
+ pub(super) fn as_timestamp(
120
+ id: LogicalTypeId,
121
+ value: &Value,
122
+ unit: TimestampUnit,
123
+ timezone_utc: bool,
124
+ ) -> Result<i64> {
125
+ match value {
126
+ Value::Timestamp(value) if value.unit == unit && value.timezone_utc == timezone_utc => {
127
+ Ok(value.value)
128
+ }
129
+ other => Err(mismatch(id, other)),
130
+ }
131
+ }
132
+
133
+ pub(super) fn as_interval(id: LogicalTypeId, value: &Value) -> Result<IntervalMonthDayNano> {
134
+ match value {
135
+ Value::Interval(value) => {
136
+ let nanoseconds = value.micros.checked_mul(NANOS_PER_MICRO).ok_or_else(|| {
137
+ QuackError::protocol(format!(
138
+ "INTERVAL of {} microseconds overflows Arrow nanosecond resolution",
139
+ value.micros
140
+ ))
141
+ })?;
142
+ Ok(IntervalMonthDayNano::new(
143
+ value.months,
144
+ value.days,
145
+ nanoseconds,
146
+ ))
147
+ }
148
+ other => Err(mismatch(id, other)),
149
+ }
150
+ }
@@ -0,0 +1,504 @@
1
+ use crate::constants::FIELD_END;
2
+ use crate::errors::{QuackError, Result};
3
+
4
+ #[derive(Clone, Copy, Debug, PartialEq, Eq)]
5
+ pub(crate) struct HugeIntParts {
6
+ pub(crate) upper: i64,
7
+ pub(crate) lower: u64,
8
+ }
9
+
10
+ impl std::fmt::Display for HugeIntParts {
11
+ /// Formats the value as a UUID string
12
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13
+ // DuckDB stores UUIDs as HUGEINT with the most significant bit flipped;
14
+ // flip it back so the output matches the server-side UUID string.
15
+ let upper = (self.upper as u64) ^ (1u64 << 63);
16
+ write!(
17
+ f,
18
+ "{:08x}-{:04x}-{:04x}-{:04x}-{:012x}",
19
+ upper >> 32,
20
+ (upper >> 16) & 0xffff,
21
+ upper & 0xffff,
22
+ self.lower >> 48,
23
+ self.lower & 0x0000_ffff_ffff_ffff
24
+ )
25
+ }
26
+ }
27
+
28
+ #[derive(Clone, Debug, Default)]
29
+ pub(crate) struct BinaryWriter {
30
+ buffer: Vec<u8>,
31
+ }
32
+
33
+ impl BinaryWriter {
34
+ pub(crate) fn new() -> Self {
35
+ Self {
36
+ buffer: Vec::with_capacity(1024),
37
+ }
38
+ }
39
+
40
+ pub(crate) fn with_capacity(capacity: usize) -> Self {
41
+ Self {
42
+ buffer: Vec::with_capacity(capacity),
43
+ }
44
+ }
45
+
46
+ pub(crate) fn into_bytes(self) -> Vec<u8> {
47
+ self.buffer
48
+ }
49
+
50
+ pub(crate) fn as_slice(&self) -> &[u8] {
51
+ &self.buffer
52
+ }
53
+
54
+ pub(crate) fn write_object(
55
+ &mut self,
56
+ write: impl FnOnce(&mut Self) -> Result<()>,
57
+ ) -> Result<()> {
58
+ write(self)?;
59
+ self.write_field_id(FIELD_END)
60
+ }
61
+
62
+ pub(crate) fn write_field(
63
+ &mut self,
64
+ field_id: u16,
65
+ write: impl FnOnce(&mut Self) -> Result<()>,
66
+ ) -> Result<()> {
67
+ self.write_field_id(field_id)?;
68
+ write(self)
69
+ }
70
+
71
+ pub(crate) fn write_field_id(&mut self, field_id: u16) -> Result<()> {
72
+ self.buffer.extend_from_slice(&field_id.to_le_bytes());
73
+ Ok(())
74
+ }
75
+
76
+ pub(crate) fn write_byte(&mut self, value: u8) -> Result<()> {
77
+ self.buffer.push(value);
78
+ Ok(())
79
+ }
80
+
81
+ pub(crate) fn write_bytes(&mut self, value: &[u8]) -> Result<()> {
82
+ self.buffer.extend_from_slice(value);
83
+ Ok(())
84
+ }
85
+
86
+ pub(crate) fn write_bool(&mut self, value: bool) -> Result<()> {
87
+ self.write_byte(if value { 1 } else { 0 })
88
+ }
89
+
90
+ pub(crate) fn write_uleb(&mut self, value: impl Into<u128>) -> Result<()> {
91
+ let mut current = value.into();
92
+ while current >= 0x80 {
93
+ self.write_byte(((current & 0x7f) as u8) | 0x80)?;
94
+ current >>= 7;
95
+ }
96
+ self.write_byte(current as u8)
97
+ }
98
+
99
+ pub(crate) fn write_sleb(&mut self, value: impl Into<i128>) -> Result<()> {
100
+ let mut current = value.into();
101
+ loop {
102
+ let mut byte = (current & 0x7f) as u8;
103
+ current >>= 7;
104
+ let sign_bit_set = (byte & 0x40) != 0;
105
+ let done = (current == 0 && !sign_bit_set) || (current == -1 && sign_bit_set);
106
+ if !done {
107
+ byte |= 0x80;
108
+ }
109
+ self.write_byte(byte)?;
110
+ if done {
111
+ return Ok(());
112
+ }
113
+ }
114
+ }
115
+
116
+ pub(crate) fn write_string(&mut self, value: &str) -> Result<()> {
117
+ self.write_string_bytes(value.as_bytes())
118
+ }
119
+
120
+ pub(crate) fn write_string_bytes(&mut self, value: &[u8]) -> Result<()> {
121
+ self.write_uleb(value.len() as u128)?;
122
+ self.write_bytes(value)
123
+ }
124
+
125
+ pub(crate) fn write_blob(&mut self, value: &[u8]) -> Result<()> {
126
+ self.write_uleb(value.len() as u128)?;
127
+ self.write_bytes(value)
128
+ }
129
+
130
+ pub(crate) fn write_list<T>(
131
+ &mut self,
132
+ items: &[T],
133
+ mut write_element: impl FnMut(&mut Self, &T, usize) -> Result<()>,
134
+ ) -> Result<()> {
135
+ self.write_uleb(items.len() as u128)?;
136
+ for (index, item) in items.iter().enumerate() {
137
+ write_element(self, item, index)?;
138
+ }
139
+ Ok(())
140
+ }
141
+
142
+ pub(crate) fn write_nullable<T>(
143
+ &mut self,
144
+ value: Option<&T>,
145
+ write_value: impl FnOnce(&mut Self, &T) -> Result<()>,
146
+ ) -> Result<()> {
147
+ match value {
148
+ Some(value) => {
149
+ self.write_bool(true)?;
150
+ write_value(self, value)
151
+ }
152
+ None => self.write_bool(false),
153
+ }
154
+ }
155
+
156
+ pub(crate) fn write_huge_int_parts(&mut self, value: HugeIntParts) -> Result<()> {
157
+ self.write_sleb(value.upper as i128)?;
158
+ self.write_uleb(value.lower as u128)
159
+ }
160
+
161
+ pub(crate) fn write_fixed_i8(&mut self, value: i8) -> Result<()> {
162
+ self.write_byte(value as u8)
163
+ }
164
+
165
+ pub(crate) fn write_fixed_u8(&mut self, value: u8) -> Result<()> {
166
+ self.write_byte(value)
167
+ }
168
+
169
+ pub(crate) fn write_fixed_i16(&mut self, value: i16) -> Result<()> {
170
+ self.write_bytes(&value.to_le_bytes())
171
+ }
172
+
173
+ pub(crate) fn write_fixed_u16(&mut self, value: u16) -> Result<()> {
174
+ self.write_bytes(&value.to_le_bytes())
175
+ }
176
+
177
+ pub(crate) fn write_fixed_i32(&mut self, value: i32) -> Result<()> {
178
+ self.write_bytes(&value.to_le_bytes())
179
+ }
180
+
181
+ pub(crate) fn write_fixed_u32(&mut self, value: u32) -> Result<()> {
182
+ self.write_bytes(&value.to_le_bytes())
183
+ }
184
+
185
+ pub(crate) fn write_fixed_i64(&mut self, value: i64) -> Result<()> {
186
+ self.write_bytes(&value.to_le_bytes())
187
+ }
188
+
189
+ pub(crate) fn write_fixed_u64(&mut self, value: u64) -> Result<()> {
190
+ self.write_bytes(&value.to_le_bytes())
191
+ }
192
+
193
+ pub(crate) fn write_fixed_f32(&mut self, value: f32) -> Result<()> {
194
+ self.write_bytes(&value.to_le_bytes())
195
+ }
196
+
197
+ pub(crate) fn write_fixed_f64(&mut self, value: f64) -> Result<()> {
198
+ self.write_bytes(&value.to_le_bytes())
199
+ }
200
+ }
201
+
202
+ #[derive(Clone, Debug)]
203
+ pub(crate) struct BinaryReader<'a> {
204
+ bytes: &'a [u8],
205
+ offset: usize,
206
+ incomplete: std::cell::Cell<bool>,
207
+ }
208
+
209
+ impl<'a> BinaryReader<'a> {
210
+ pub(crate) fn new(bytes: &'a [u8]) -> Self {
211
+ Self {
212
+ bytes,
213
+ offset: 0,
214
+ incomplete: std::cell::Cell::new(false),
215
+ }
216
+ }
217
+
218
+ pub(crate) fn is_incomplete(&self) -> bool {
219
+ self.incomplete.get()
220
+ }
221
+
222
+ pub(crate) fn remaining(&self) -> usize {
223
+ self.bytes.len().saturating_sub(self.offset)
224
+ }
225
+
226
+ pub(crate) fn eof(&self) -> bool {
227
+ self.remaining() == 0
228
+ }
229
+
230
+ pub(crate) fn assert_eof(&self) -> Result<()> {
231
+ if self.eof() {
232
+ Ok(())
233
+ } else {
234
+ Err(QuackError::protocol(format!(
235
+ "unexpected trailing bytes at offset {}",
236
+ self.offset
237
+ )))
238
+ }
239
+ }
240
+
241
+ pub(crate) fn read_object<T>(
242
+ &mut self,
243
+ read: impl FnOnce(&mut Self) -> Result<T>,
244
+ ) -> Result<T> {
245
+ let result = read(self)?;
246
+ self.read_end_object()?;
247
+ Ok(result)
248
+ }
249
+
250
+ pub(crate) fn read_end_object(&mut self) -> Result<()> {
251
+ let field_id = self.read_field_id()?;
252
+ if field_id != FIELD_END {
253
+ return Err(QuackError::protocol(format!(
254
+ "expected end of object at offset {}, got field {}",
255
+ self.offset - 2,
256
+ field_id
257
+ )));
258
+ }
259
+ Ok(())
260
+ }
261
+
262
+ pub(crate) fn read_field_id(&mut self) -> Result<u16> {
263
+ self.ensure(2)?;
264
+ let value = u16::from_le_bytes([self.bytes[self.offset], self.bytes[self.offset + 1]]);
265
+ self.offset += 2;
266
+ Ok(value)
267
+ }
268
+
269
+ pub(crate) fn peek_field_id(&self) -> Result<u16> {
270
+ self.ensure(2)?;
271
+ Ok(u16::from_le_bytes([
272
+ self.bytes[self.offset],
273
+ self.bytes[self.offset + 1],
274
+ ]))
275
+ }
276
+
277
+ pub(crate) fn read_required_field<T>(
278
+ &mut self,
279
+ field_id: u16,
280
+ read: impl FnOnce(&mut Self) -> Result<T>,
281
+ ) -> Result<T> {
282
+ let actual = self.read_field_id()?;
283
+ if actual != field_id {
284
+ return Err(QuackError::protocol(format!(
285
+ "expected field {} at offset {}, got {}",
286
+ field_id,
287
+ self.offset - 2,
288
+ actual
289
+ )));
290
+ }
291
+ read(self)
292
+ }
293
+
294
+ pub(crate) fn read_optional_field<T>(
295
+ &mut self,
296
+ field_id: u16,
297
+ read: impl FnOnce(&mut Self) -> Result<T>,
298
+ default_value: T,
299
+ ) -> Result<T> {
300
+ if self.peek_field_id()? != field_id {
301
+ return Ok(default_value);
302
+ }
303
+ self.read_field_id()?;
304
+ read(self)
305
+ }
306
+
307
+ pub(crate) fn read_byte(&mut self) -> Result<u8> {
308
+ self.ensure(1)?;
309
+ let value = self.bytes[self.offset];
310
+ self.offset += 1;
311
+ Ok(value)
312
+ }
313
+
314
+ pub(crate) fn read_bytes(&mut self, length: usize) -> Result<Vec<u8>> {
315
+ self.ensure(length)?;
316
+ let start = self.offset;
317
+ self.offset += length;
318
+ Ok(self.bytes[start..self.offset].to_vec())
319
+ }
320
+
321
+ pub(crate) fn read_bool(&mut self) -> Result<bool> {
322
+ match self.read_byte()? {
323
+ 0 => Ok(false),
324
+ 1 => Ok(true),
325
+ value => Err(QuackError::protocol(format!(
326
+ "invalid boolean byte {}",
327
+ value
328
+ ))),
329
+ }
330
+ }
331
+
332
+ pub(crate) fn read_uleb_u128(&mut self) -> Result<u128> {
333
+ let mut result = 0u128;
334
+ let mut shift = 0u32;
335
+ for _ in 0..19 {
336
+ let byte = self.read_byte()?;
337
+ result |= ((byte & 0x7f) as u128) << shift;
338
+ if (byte & 0x80) == 0 {
339
+ return Ok(result);
340
+ }
341
+ shift += 7;
342
+ }
343
+ Err(QuackError::protocol("unsigned LEB128 value is too long"))
344
+ }
345
+
346
+ pub(crate) fn read_uleb_u64(&mut self) -> Result<u64> {
347
+ u64::try_from(self.read_uleb_u128()?)
348
+ .map_err(|_| QuackError::protocol("unsigned LEB128 value exceeds u64"))
349
+ }
350
+
351
+ pub(crate) fn read_uleb_usize(&mut self) -> Result<usize> {
352
+ usize::try_from(self.read_uleb_u128()?)
353
+ .map_err(|_| QuackError::protocol("unsigned LEB128 value exceeds usize"))
354
+ }
355
+
356
+ pub(crate) fn read_sleb_i128(&mut self) -> Result<i128> {
357
+ let mut result = 0i128;
358
+ let mut shift = 0u32;
359
+ for _ in 0..19 {
360
+ let byte = self.read_byte()?;
361
+ result |= ((byte & 0x7f) as i128) << shift;
362
+ shift += 7;
363
+ if (byte & 0x80) == 0 {
364
+ if (byte & 0x40) != 0 {
365
+ result |= (-1i128) << shift;
366
+ }
367
+ return Ok(result);
368
+ }
369
+ }
370
+ Err(QuackError::protocol("signed LEB128 value is too long"))
371
+ }
372
+
373
+ pub(crate) fn read_sleb_i64(&mut self) -> Result<i64> {
374
+ i64::try_from(self.read_sleb_i128()?)
375
+ .map_err(|_| QuackError::protocol("signed LEB128 value exceeds i64"))
376
+ }
377
+
378
+ pub(crate) fn read_string(&mut self) -> Result<String> {
379
+ String::from_utf8(self.read_string_bytes()?).map_err(Into::into)
380
+ }
381
+
382
+ pub(crate) fn read_string_bytes(&mut self) -> Result<Vec<u8>> {
383
+ let length = self.read_uleb_usize()?;
384
+ self.read_bytes(length)
385
+ }
386
+
387
+ pub(crate) fn read_blob(&mut self) -> Result<Vec<u8>> {
388
+ let length = self.read_uleb_usize()?;
389
+ self.read_bytes(length)
390
+ }
391
+
392
+ pub(crate) fn read_list<T>(
393
+ &mut self,
394
+ mut read_element: impl FnMut(&mut Self, usize) -> Result<T>,
395
+ ) -> Result<Vec<T>> {
396
+ let length = self.read_uleb_usize()?;
397
+ let mut result = Vec::with_capacity(length);
398
+ for index in 0..length {
399
+ result.push(read_element(self, index)?);
400
+ }
401
+ Ok(result)
402
+ }
403
+
404
+ pub(crate) fn read_nullable<T>(
405
+ &mut self,
406
+ read_value: impl FnOnce(&mut Self) -> Result<T>,
407
+ ) -> Result<Option<T>> {
408
+ if self.read_bool()? {
409
+ Ok(Some(read_value(self)?))
410
+ } else {
411
+ Ok(None)
412
+ }
413
+ }
414
+
415
+ pub(crate) fn read_huge_int_parts(&mut self) -> Result<HugeIntParts> {
416
+ let upper = self.read_sleb_i64()?;
417
+ let lower = self.read_uleb_u64()?;
418
+ Ok(HugeIntParts { upper, lower })
419
+ }
420
+
421
+ pub(crate) fn read_fixed_i8(&mut self) -> Result<i8> {
422
+ Ok(self.read_byte()? as i8)
423
+ }
424
+
425
+ pub(crate) fn read_fixed_u8(&mut self) -> Result<u8> {
426
+ self.read_byte()
427
+ }
428
+
429
+ pub(crate) fn read_fixed_i16(&mut self) -> Result<i16> {
430
+ let bytes = self.read_array::<2>()?;
431
+ Ok(i16::from_le_bytes(bytes))
432
+ }
433
+
434
+ pub(crate) fn read_fixed_u16(&mut self) -> Result<u16> {
435
+ let bytes = self.read_array::<2>()?;
436
+ Ok(u16::from_le_bytes(bytes))
437
+ }
438
+
439
+ pub(crate) fn read_fixed_i32(&mut self) -> Result<i32> {
440
+ let bytes = self.read_array::<4>()?;
441
+ Ok(i32::from_le_bytes(bytes))
442
+ }
443
+
444
+ pub(crate) fn read_fixed_u32(&mut self) -> Result<u32> {
445
+ let bytes = self.read_array::<4>()?;
446
+ Ok(u32::from_le_bytes(bytes))
447
+ }
448
+
449
+ pub(crate) fn read_fixed_i64(&mut self) -> Result<i64> {
450
+ let bytes = self.read_array::<8>()?;
451
+ Ok(i64::from_le_bytes(bytes))
452
+ }
453
+
454
+ pub(crate) fn read_fixed_u64(&mut self) -> Result<u64> {
455
+ let bytes = self.read_array::<8>()?;
456
+ Ok(u64::from_le_bytes(bytes))
457
+ }
458
+
459
+ pub(crate) fn read_fixed_f32(&mut self) -> Result<f32> {
460
+ let bytes = self.read_array::<4>()?;
461
+ Ok(f32::from_le_bytes(bytes))
462
+ }
463
+
464
+ pub(crate) fn read_fixed_f64(&mut self) -> Result<f64> {
465
+ let bytes = self.read_array::<8>()?;
466
+ Ok(f64::from_le_bytes(bytes))
467
+ }
468
+
469
+ fn read_array<const N: usize>(&mut self) -> Result<[u8; N]> {
470
+ self.ensure(N)?;
471
+ let mut bytes = [0u8; N];
472
+ bytes.copy_from_slice(&self.bytes[self.offset..self.offset + N]);
473
+ self.offset += N;
474
+ Ok(bytes)
475
+ }
476
+
477
+ fn ensure(&self, length: usize) -> Result<()> {
478
+ if length > self.remaining() {
479
+ self.incomplete.set(true);
480
+ return Err(QuackError::protocol(format!(
481
+ "unexpected end of input at offset {}; needed {} byte(s), have {}",
482
+ self.offset,
483
+ length,
484
+ self.remaining()
485
+ )));
486
+ }
487
+ Ok(())
488
+ }
489
+ }
490
+
491
+ pub(crate) fn split_signed_huge_int(value: i128) -> HugeIntParts {
492
+ HugeIntParts {
493
+ upper: (value >> 64) as i64,
494
+ lower: value as u64,
495
+ }
496
+ }
497
+
498
+ pub(crate) fn combine_signed_huge_int(parts: HugeIntParts) -> i128 {
499
+ ((parts.upper as i128) << 64) | (parts.lower as i128)
500
+ }
501
+
502
+ pub(crate) fn combine_unsigned_huge_int(parts: HugeIntParts) -> u128 {
503
+ ((parts.upper as u64 as u128) << 64) | parts.lower as u128
504
+ }