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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/LICENSE-DuckDB +7 -0
- data/LICENSE-QuackProtocol +21 -0
- data/LICENSE-Rust-dependencies.json +2057 -0
- data/README.md +229 -0
- data/ext/quack/Cargo.lock +1803 -0
- data/ext/quack/Cargo.toml +17 -0
- data/ext/quack/extconf.rb +4 -0
- data/ext/quack/src/lib.rs +647 -0
- data/ext/quack/vendor/quack_protocol/Cargo.lock +1907 -0
- data/ext/quack/vendor/quack_protocol/Cargo.toml +41 -0
- data/ext/quack/vendor/quack_protocol/LICENSE +21 -0
- data/ext/quack/vendor/quack_protocol/PATCHES.md +16 -0
- data/ext/quack/vendor/quack_protocol/README.md +272 -0
- data/ext/quack/vendor/quack_protocol/src/arrow/columns.rs +399 -0
- data/ext/quack/vendor/quack_protocol/src/arrow/mod.rs +134 -0
- data/ext/quack/vendor/quack_protocol/src/arrow/schema.rs +103 -0
- data/ext/quack/vendor/quack_protocol/src/arrow/tests.rs +851 -0
- data/ext/quack/vendor/quack_protocol/src/arrow/values.rs +150 -0
- data/ext/quack/vendor/quack_protocol/src/binary.rs +504 -0
- data/ext/quack/vendor/quack_protocol/src/builders.rs +217 -0
- data/ext/quack/vendor/quack_protocol/src/client.rs +1486 -0
- data/ext/quack/vendor/quack_protocol/src/constants.rs +11 -0
- data/ext/quack/vendor/quack_protocol/src/errors.rs +103 -0
- data/ext/quack/vendor/quack_protocol/src/inspection.rs +250 -0
- data/ext/quack/vendor/quack_protocol/src/json.rs +225 -0
- data/ext/quack/vendor/quack_protocol/src/lib.rs +54 -0
- data/ext/quack/vendor/quack_protocol/src/logical_types.rs +977 -0
- data/ext/quack/vendor/quack_protocol/src/messages.rs +843 -0
- data/ext/quack/vendor/quack_protocol/src/pool.rs +741 -0
- data/ext/quack/vendor/quack_protocol/src/protocol_tests.rs +759 -0
- data/ext/quack/vendor/quack_protocol/src/proxy_error.rs +77 -0
- data/ext/quack/vendor/quack_protocol/src/sql.rs +359 -0
- data/ext/quack/vendor/quack_protocol/src/tls.rs +354 -0
- data/ext/quack/vendor/quack_protocol/src/values.rs +77 -0
- data/ext/quack/vendor/quack_protocol/src/vector.rs +1364 -0
- data/ext/quack/vendor/quack_protocol/testdata/tls/key.der +0 -0
- data/ext/quack/vendor/quack_protocol/testdata/tls/spki.der +0 -0
- data/ext/quack/vendor/quack_protocol/testdata/tls/v1-cert.der +0 -0
- data/ext/quack/vendor/quack_protocol/testdata/tls/v3-cert.der +0 -0
- data/lib/quack/codec.rb +263 -0
- data/lib/quack/connection.rb +131 -0
- data/lib/quack/logical_types.rb +72 -0
- data/lib/quack/result.rb +64 -0
- data/lib/quack/sql.rb +183 -0
- data/lib/quack/types.rb +40 -0
- data/lib/quack/variant.rb +298 -0
- data/lib/quack.rb +34 -0
- 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
|
+
}
|