client-query-cache 0.9.1__tar.gz → 0.10.0__tar.gz
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.
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/PKG-INFO +1 -1
- client_query_cache-0.10.0/native/shared-index/src/key_encoder.rs +224 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/native/shared-index/src/lib.rs +4 -0
- client_query_cache-0.10.0/native/shared-index/src/local_cache.rs +2872 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/native/shared-index/src/python.rs +4 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/pyproject.toml +4 -1
- client_query_cache-0.10.0/src/client_query_cache/_core/contracts.pyi +209 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/cursor_capture.py +3 -3
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/entries.py +4 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/manager.py +28 -12
- client_query_cache-0.10.0/src/client_query_cache/_core/native.py +121 -0
- client_query_cache-0.9.1/src/client_query_cache/_core/residency.py → client_query_cache-0.10.0/src/client_query_cache/_core/residency.pyi +8 -20
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/stream_events.py +1 -1
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_shared/adapters.py +20 -24
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_shared/shared_index.py +5 -1
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_shared/wire.py +49 -2
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_shared_index.pyi +21 -0
- {client_query_cache-0.9.1/src/client_query_cache/synchronous → client_query_cache-0.10.0/src/client_query_cache/asynchronous}/__init__.py +2 -1
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/asynchronous/manager.py +1 -1
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/asynchronous/streams.py +1 -1
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/shared.py +5 -2
- {client_query_cache-0.9.1/src/client_query_cache/asynchronous → client_query_cache-0.10.0/src/client_query_cache/synchronous}/__init__.py +2 -1
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/synchronous/manager.py +1 -1
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/synchronous/streams.py +1 -1
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/LICENSE +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/README.md +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/native/shared-index/Cargo.lock +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/native/shared-index/Cargo.toml +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/native/shared-index/deny.toml +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/native/shared-index/src/clock.rs +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/native/shared-index/src/echo/tests.rs +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/native/shared-index/src/echo.rs +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/native/shared-index/src/frames/tests.rs +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/native/shared-index/src/frames.rs +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/native/shared-index/src/hash/tests.rs +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/native/shared-index/src/hash.rs +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/native/shared-index/src/index/support_tests.rs +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/native/shared-index/src/index/tests.rs +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/native/shared-index/src/index.rs +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/native/shared-index/src/memory/support_tests.rs +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/native/shared-index/src/memory/tests.rs +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/native/shared-index/src/memory.rs +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/native/shared-index/src/relay/tests.rs +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/native/shared-index/src/relay.rs +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/native/shared-index/src/ring/tests.rs +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/native/shared-index/src/ring.rs +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/native/shared-index/src/sync.rs +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/__init__.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/__init__.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/canonical.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/codec.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/collation.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/collection_metadata.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/count_reads.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/errors.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/find_one_reads.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/find_reads.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/identity_reads.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/keys.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/lifecycle.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/locking.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/lru.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/namespace.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/namespace_metadata.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/order_sensitive_keys.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/projection.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/query_filters.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/read_classification.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/read_validation.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/snapshots.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/stream_activation.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/stream_cost.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/stream_health.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/stream_options.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/stream_startup.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/traversal.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_core/unique_keys.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_shared/__init__.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_shared/attachment.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_shared/coordinator.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/_types.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/asynchronous/collection.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/asynchronous/cursors.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/asynchronous/database.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/asynchronous/shared.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/otel.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/py.typed +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/synchronous/collection.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/synchronous/cursors.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/synchronous/database.py +0 -0
- {client_query_cache-0.9.1 → client_query_cache-0.10.0}/src/client_query_cache/synchronous/shared.py +0 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
//! The shared key envelope follows https://bsonspec.org/spec.html. Specialized
|
|
2
|
+
//! scalar representations stay with the Python wire codec and PyMongo's encoder.
|
|
3
|
+
use pyo3::exceptions::{PyOverflowError, PyValueError};
|
|
4
|
+
use pyo3::prelude::*;
|
|
5
|
+
use pyo3::types::{PyBool, PyBytes, PyDict, PyFloat, PyInt, PyString, PyTuple};
|
|
6
|
+
|
|
7
|
+
type FindKeys<'py> = (Bound<'py, PyBytes>, Bound<'py, PyBytes>);
|
|
8
|
+
|
|
9
|
+
struct Recursion;
|
|
10
|
+
|
|
11
|
+
impl Recursion {
|
|
12
|
+
fn enter(py: Python<'_>) -> PyResult<Self> {
|
|
13
|
+
// CPython's recursion guard covers calls crossing the extension boundary.
|
|
14
|
+
if unsafe { pyo3::ffi::Py_EnterRecursiveCall(c" while encoding a cache key".as_ptr()) } != 0
|
|
15
|
+
{
|
|
16
|
+
return Err(PyErr::fetch(py));
|
|
17
|
+
}
|
|
18
|
+
Ok(Self)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
impl Drop for Recursion {
|
|
23
|
+
fn drop(&mut self) {
|
|
24
|
+
unsafe { pyo3::ffi::Py_LeaveRecursiveCall() };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
fn encoded_value(encoded: &[u8]) -> PyResult<(u8, &[u8])> {
|
|
29
|
+
match encoded {
|
|
30
|
+
[a, b, c, d, kind, b'k', 0, payload @ .., 0]
|
|
31
|
+
if usize::try_from(i32::from_le_bytes([*a, *b, *c, *d])).ok()
|
|
32
|
+
== Some(encoded.len()) =>
|
|
33
|
+
{
|
|
34
|
+
Ok((*kind, payload))
|
|
35
|
+
}
|
|
36
|
+
_ => Err(PyValueError::new_err("invalid encoded key envelope")),
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
fn length(value: usize) -> PyResult<[u8; 4]> {
|
|
41
|
+
i32::try_from(value)
|
|
42
|
+
.map(i32::to_le_bytes)
|
|
43
|
+
.map_err(|_| PyOverflowError::new_err("cache key exceeds BSON length"))
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
fn start(buffer: &mut Vec<u8>) -> usize {
|
|
47
|
+
let offset = buffer.len();
|
|
48
|
+
buffer.extend_from_slice(&[0; 4]);
|
|
49
|
+
offset
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
fn finish(buffer: &mut Vec<u8>, offset: usize) -> PyResult<()> {
|
|
53
|
+
buffer.push(0);
|
|
54
|
+
let size = length(buffer.len() - offset)?;
|
|
55
|
+
buffer[offset..offset + 4].copy_from_slice(&size);
|
|
56
|
+
Ok(())
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
fn header(buffer: &mut Vec<u8>, kind: u8, name: &str) {
|
|
60
|
+
buffer.push(kind);
|
|
61
|
+
buffer.extend_from_slice(name.as_bytes());
|
|
62
|
+
buffer.push(0);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
fn string(buffer: &mut Vec<u8>, name: &str, value: &str) -> PyResult<()> {
|
|
66
|
+
header(buffer, 2, name);
|
|
67
|
+
buffer.extend_from_slice(&length(value.len() + 1)?);
|
|
68
|
+
buffer.extend_from_slice(value.as_bytes());
|
|
69
|
+
buffer.push(0);
|
|
70
|
+
Ok(())
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
fn tagged(buffer: &mut Vec<u8>, name: &str, tag: &str) -> PyResult<usize> {
|
|
74
|
+
header(buffer, 3, name);
|
|
75
|
+
let offset = start(buffer);
|
|
76
|
+
string(buffer, "t", tag)?;
|
|
77
|
+
Ok(offset)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
fn tuple(buffer: &mut Vec<u8>, name: &str) -> PyResult<(usize, usize)> {
|
|
81
|
+
let document = tagged(buffer, name, "tuple")?;
|
|
82
|
+
header(buffer, 4, "p");
|
|
83
|
+
Ok((document, start(buffer)))
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
fn finish_tuple(buffer: &mut Vec<u8>, offsets: (usize, usize)) -> PyResult<()> {
|
|
87
|
+
finish(buffer, offsets.1)?;
|
|
88
|
+
finish(buffer, offsets.0)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
#[pyclass(frozen)]
|
|
92
|
+
pub(crate) struct FindKeyEncoder {
|
|
93
|
+
tags: Vec<(usize, String)>,
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
impl FindKeyEncoder {
|
|
97
|
+
fn node(
|
|
98
|
+
&self,
|
|
99
|
+
buffer: &mut Vec<u8>,
|
|
100
|
+
name: &str,
|
|
101
|
+
value: &Bound<'_, PyAny>,
|
|
102
|
+
scalar_encoder: &Bound<'_, PyAny>,
|
|
103
|
+
) -> PyResult<()> {
|
|
104
|
+
if let Ok(items) = value.cast::<PyTuple>() {
|
|
105
|
+
let _recursion = Recursion::enter(value.py())?;
|
|
106
|
+
let offsets = tuple(buffer, name)?;
|
|
107
|
+
for (index, item) in items.iter().enumerate() {
|
|
108
|
+
self.node(buffer, &index.to_string(), &item, scalar_encoder)?;
|
|
109
|
+
}
|
|
110
|
+
return finish_tuple(buffer, offsets);
|
|
111
|
+
}
|
|
112
|
+
if value.is_none() {
|
|
113
|
+
header(buffer, 10, name);
|
|
114
|
+
} else if value.is_exact_instance_of::<PyBool>() {
|
|
115
|
+
header(buffer, 8, name);
|
|
116
|
+
buffer.push(u8::from(value.extract::<bool>()?));
|
|
117
|
+
} else if value.is_exact_instance_of::<PyInt>() {
|
|
118
|
+
if let Ok(integer) = value.extract::<i64>() {
|
|
119
|
+
let offset = tagged(buffer, name, "int")?;
|
|
120
|
+
header(buffer, 18, "p");
|
|
121
|
+
buffer.extend_from_slice(&integer.to_le_bytes());
|
|
122
|
+
finish(buffer, offset)?;
|
|
123
|
+
} else {
|
|
124
|
+
scalar(buffer, name, value, scalar_encoder)?;
|
|
125
|
+
}
|
|
126
|
+
} else if value.is_exact_instance_of::<PyString>() {
|
|
127
|
+
string(buffer, name, value.cast::<PyString>()?.to_str()?)?;
|
|
128
|
+
} else if value.is_exact_instance_of::<PyBytes>() {
|
|
129
|
+
let bytes = value.cast::<PyBytes>()?.as_bytes();
|
|
130
|
+
header(buffer, 5, name);
|
|
131
|
+
buffer.extend_from_slice(&length(bytes.len())?);
|
|
132
|
+
buffer.push(0);
|
|
133
|
+
buffer.extend_from_slice(bytes);
|
|
134
|
+
} else if value.is_exact_instance_of::<PyFloat>() {
|
|
135
|
+
header(buffer, 1, name);
|
|
136
|
+
buffer.extend_from_slice(&value.extract::<f64>()?.to_le_bytes());
|
|
137
|
+
} else if let Some((_, tag)) = self
|
|
138
|
+
.tags
|
|
139
|
+
.iter()
|
|
140
|
+
.find(|(identity, _)| *identity == value.as_ptr() as usize)
|
|
141
|
+
{
|
|
142
|
+
let offset = tagged(buffer, name, "tag")?;
|
|
143
|
+
string(buffer, "p", tag)?;
|
|
144
|
+
finish(buffer, offset)?;
|
|
145
|
+
} else {
|
|
146
|
+
scalar(buffer, name, value, scalar_encoder)?;
|
|
147
|
+
}
|
|
148
|
+
Ok(())
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
fn scalar(
|
|
153
|
+
buffer: &mut Vec<u8>,
|
|
154
|
+
name: &str,
|
|
155
|
+
value: &Bound<'_, PyAny>,
|
|
156
|
+
scalar_encoder: &Bound<'_, PyAny>,
|
|
157
|
+
) -> PyResult<()> {
|
|
158
|
+
let encoded = scalar_encoder.call1((value,))?;
|
|
159
|
+
let bytes = encoded.cast::<PyBytes>()?.as_bytes();
|
|
160
|
+
// The existing encoder returns one BSON element named "k". Reuse its
|
|
161
|
+
// complete value, including BSON subtype and specialized tagged nodes.
|
|
162
|
+
let (kind, payload) = encoded_value(bytes)?;
|
|
163
|
+
header(buffer, kind, name);
|
|
164
|
+
buffer.extend_from_slice(payload);
|
|
165
|
+
Ok(())
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
impl FindKeyEncoder {
|
|
169
|
+
fn new(tags: &Bound<'_, PyDict>) -> PyResult<Self> {
|
|
170
|
+
let tags = tags
|
|
171
|
+
.iter()
|
|
172
|
+
.map(|(identity, name)| Ok((identity.extract::<usize>()?, name.extract::<String>()?)))
|
|
173
|
+
.collect::<PyResult<_>>()?;
|
|
174
|
+
Ok(Self { tags })
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
#[pyfunction]
|
|
179
|
+
pub(crate) fn find_key_encoder(tags: &Bound<'_, PyDict>) -> PyResult<FindKeyEncoder> {
|
|
180
|
+
FindKeyEncoder::new(tags)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
#[pymethods]
|
|
184
|
+
impl FindKeyEncoder {
|
|
185
|
+
fn encode<'py>(
|
|
186
|
+
&self,
|
|
187
|
+
py: Python<'py>,
|
|
188
|
+
family: &Bound<'py, PyAny>,
|
|
189
|
+
limit: &Bound<'py, PyAny>,
|
|
190
|
+
scalar_encoder: &Bound<'py, PyAny>,
|
|
191
|
+
) -> PyResult<FindKeys<'py>> {
|
|
192
|
+
let mut family_bytes = Vec::with_capacity(256);
|
|
193
|
+
let root = start(&mut family_bytes);
|
|
194
|
+
self.node(&mut family_bytes, "k", family, scalar_encoder)?;
|
|
195
|
+
finish(&mut family_bytes, root)?;
|
|
196
|
+
|
|
197
|
+
let exact = self.wrap(py, &family_bytes, limit, scalar_encoder)?;
|
|
198
|
+
Ok((PyBytes::new(py, &family_bytes), exact))
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
fn wrap<'py>(
|
|
202
|
+
&self,
|
|
203
|
+
py: Python<'py>,
|
|
204
|
+
family_bytes: &[u8],
|
|
205
|
+
limit: &Bound<'py, PyAny>,
|
|
206
|
+
scalar_encoder: &Bound<'py, PyAny>,
|
|
207
|
+
) -> PyResult<Bound<'py, PyBytes>> {
|
|
208
|
+
let mut exact = Vec::with_capacity(family_bytes.len() + 128);
|
|
209
|
+
let root = start(&mut exact);
|
|
210
|
+
let outer = tuple(&mut exact, "k")?;
|
|
211
|
+
let tag = tagged(&mut exact, "0", "tag")?;
|
|
212
|
+
string(&mut exact, "p", "canonical-seq")?;
|
|
213
|
+
finish(&mut exact, tag)?;
|
|
214
|
+
let pair = tuple(&mut exact, "1")?;
|
|
215
|
+
let (kind, payload) = encoded_value(family_bytes)?;
|
|
216
|
+
header(&mut exact, kind, "0");
|
|
217
|
+
exact.extend_from_slice(payload);
|
|
218
|
+
self.node(&mut exact, "1", limit, scalar_encoder)?;
|
|
219
|
+
finish_tuple(&mut exact, pair)?;
|
|
220
|
+
finish_tuple(&mut exact, outer)?;
|
|
221
|
+
finish(&mut exact, root)?;
|
|
222
|
+
Ok(PyBytes::new(py, &exact))
|
|
223
|
+
}
|
|
224
|
+
}
|
|
@@ -16,6 +16,10 @@ mod echo;
|
|
|
16
16
|
mod frames;
|
|
17
17
|
mod hash;
|
|
18
18
|
mod index;
|
|
19
|
+
#[cfg(all(feature = "python", not(loom)))]
|
|
20
|
+
mod key_encoder;
|
|
21
|
+
#[cfg(all(feature = "python", not(loom)))]
|
|
22
|
+
mod local_cache;
|
|
19
23
|
mod memory;
|
|
20
24
|
#[cfg(all(feature = "python", not(loom)))]
|
|
21
25
|
mod python;
|