Skip to content

Commit ddaac19

Browse files
committed
Change get expressions to copy instead of mutate. Fixed division support
1 parent bf510c0 commit ddaac19

3 files changed

Lines changed: 72 additions & 68 deletions

File tree

src/combinators/get.rs

Lines changed: 53 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -42,30 +42,33 @@ pub struct Get {
4242
}
4343

4444
impl Get {
45-
fn op(&mut self, other: Bound<PyAny>, op: Item, rev: bool) -> PyResult<()> {
45+
fn op(&self, other: Bound<PyAny>, op: Item, rev: bool) -> PyResult<Self> {
46+
let mut new = self.clone();
4647
if let Ok(other) = other.extract::<Self>() {
47-
self.rpn.reserve(other.rpn.len());
48+
new.rpn.reserve(other.rpn.len());
4849
if rev {
4950
for item in other.rpn.into_iter().rev() {
50-
self.rpn.push_front(item);
51+
new.rpn.push_front(item);
5152
}
5253
} else {
5354
for item in other.rpn {
54-
self.rpn.push_back(item);
55+
new.rpn.push_back(item);
5556
}
5657
}
57-
self.rpn.push_back(op);
58+
new.rpn.push_back(op);
5859
} else if let Ok(num) = other.extract::<i128>() {
5960
if rev {
60-
self.rpn.push_front(Item::Int(num));
61+
new.rpn.push_front(Item::Int(num));
6162
} else {
62-
self.rpn.push_back(Item::Int(num));
63+
new.rpn.push_back(Item::Int(num));
6364
}
64-
self.rpn.push_back(op);
65+
new.rpn.push_back(op);
6566
} else {
66-
return Err(PyValueError::new_err("Cannot operate on values other than refs and ints"));
67+
return Err(PyValueError::new_err(format!(
68+
"Cannot operate on values other than refs and ints: '{}'", other
69+
)));
6770
}
68-
Ok(())
71+
Ok(new)
6972
}
7073

7174
pub fn new(target: Item) -> Self {
@@ -273,79 +276,65 @@ impl Get {
273276
// this is all boilerplate, refer to the op fn
274277
#[pymethods]
275278
impl Get {
276-
pub fn __add__<'py>(mut slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<PyRefMut<'py, Self>> {
277-
slf.op(other, Item::Add, false)?;
278-
Ok(slf)
279+
pub fn __add__<'py>(slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<Self> {
280+
slf.op(other, Item::Add, false)
279281
}
280-
pub fn __radd__<'py>(mut slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<PyRefMut<'py, Self>> {
281-
slf.op(other, Item::Add, true)?;
282-
Ok(slf)
282+
pub fn __radd__<'py>(slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<Self> {
283+
slf.op(other, Item::Add, true)
283284
}
284-
pub fn __sub__<'py>(mut slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<PyRefMut<'py, Self>> {
285-
slf.op(other, Item::Sub, false)?;
286-
Ok(slf)
285+
pub fn __sub__<'py>(slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<Self> {
286+
slf.op(other, Item::Sub, false)
287287
}
288-
pub fn __rsub__<'py>(mut slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<PyRefMut<'py, Self>> {
289-
slf.op(other, Item::Sub, true)?;
290-
Ok(slf)
288+
pub fn __rsub__<'py>(slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<Self> {
289+
slf.op(other, Item::Sub, true)
291290
}
292-
pub fn __mul__<'py>(mut slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<PyRefMut<'py, Self>> {
293-
slf.op(other, Item::Mul, false)?;
294-
Ok(slf)
291+
pub fn __mul__<'py>(slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<Self> {
292+
slf.op(other, Item::Mul, false)
295293
}
296-
pub fn __rmul__<'py>(mut slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<PyRefMut<'py, Self>> {
297-
slf.op(other, Item::Mul, true)?;
298-
Ok(slf)
294+
pub fn __rmul__<'py>(slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<Self> {
295+
slf.op(other, Item::Mul, true)
299296
}
300-
pub fn __div__<'py>(mut slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<PyRefMut<'py, Self>> {
301-
slf.op(other, Item::Div, false)?;
302-
Ok(slf)
297+
pub fn __floordiv__<'py>(slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<Self> {
298+
slf.op(other, Item::Div, false)
303299
}
304-
pub fn __rdiv__<'py>(mut slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<PyRefMut<'py, Self>> {
305-
slf.op(other, Item::Div, true)?;
306-
Ok(slf)
300+
pub fn __rfloordiv__<'py>(slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<Self> {
301+
slf.op(other, Item::Div, true)
307302
}
308-
pub fn __mod__<'py>(mut slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<PyRefMut<'py, Self>> {
309-
slf.op(other, Item::Mod, false)?;
310-
Ok(slf)
303+
pub fn __mod__<'py>(slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<Self> {
304+
slf.op(other, Item::Mod, false)
311305
}
312-
pub fn __rmod__<'py>(mut slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<PyRefMut<'py, Self>> {
313-
slf.op(other, Item::Mod, true)?;
314-
Ok(slf)
306+
pub fn __rmod__<'py>(slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<Self> {
307+
slf.op(other, Item::Mod, true)
315308
}
316309

317-
pub fn __and__<'py>(mut slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<PyRefMut<'py, Self>> {
318-
slf.op(other, Item::BitAnd, false)?;
319-
Ok(slf)
310+
pub fn __and__<'py>(slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<Self> {
311+
slf.op(other, Item::BitAnd, false)
320312
}
321-
pub fn __rand__<'py>(mut slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<PyRefMut<'py, Self>> {
322-
slf.op(other, Item::BitAnd, true)?;
323-
Ok(slf)
313+
pub fn __rand__<'py>(slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<Self> {
314+
slf.op(other, Item::BitAnd, true)
324315
}
325-
pub fn __or__<'py>(mut slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<PyRefMut<'py, Self>> {
326-
slf.op(other, Item::BitOr, false)?;
327-
Ok(slf)
316+
pub fn __or__<'py>(slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<Self> {
317+
slf.op(other, Item::BitOr, false)
328318
}
329-
pub fn __ror__<'py>(mut slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<PyRefMut<'py, Self>> {
330-
slf.op(other, Item::BitOr, true)?;
331-
Ok(slf)
319+
pub fn __ror__<'py>(slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<Self> {
320+
slf.op(other, Item::BitOr, true)
332321
}
333-
pub fn __xor__<'py>(mut slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<PyRefMut<'py, Self>> {
334-
slf.op(other, Item::BitXor, false)?;
335-
Ok(slf)
322+
pub fn __xor__<'py>(slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<Self> {
323+
slf.op(other, Item::BitXor, false)
336324
}
337-
pub fn __rxor__<'py>(mut slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<PyRefMut<'py, Self>> {
338-
slf.op(other, Item::BitXor, true)?;
339-
Ok(slf)
325+
pub fn __rxor__<'py>(slf: PyRefMut<'py, Self>, other: Bound<PyAny>) -> PyResult<Self> {
326+
slf.op(other, Item::BitXor, true)
340327
}
341328

342-
pub fn __neg__(mut slf: PyRefMut<'_, Self>) -> PyResult<PyRefMut<'_, Self>> {
343-
slf.rpn.push_back(Item::Neg);
344-
Ok(slf)
329+
pub fn __neg__(&self) -> Self {
330+
let mut new = self.clone();
331+
new.rpn.push_back(Item::Neg);
332+
new
345333
}
346-
pub fn __invert__(mut slf: PyRefMut<'_, Self>) -> PyResult<PyRefMut<'_, Self>> {
347-
slf.rpn.push_back(Item::BitNeg);
348-
Ok(slf)
334+
pub fn __invert__(&self) -> Self {
335+
let mut new = self.clone();
336+
new.rpn.push_back(Item::BitNeg);
337+
new
349338
}
350339
}
351340

src/types/struct_builder.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,23 @@ impl StructBuilder {
5252
}
5353

5454
pub fn get_struct(cls: &Bound<PyType>) -> PyResult<Struct> {
55-
let builder = cls
56-
.getattr(intern!(cls.py(), "__struct_builder__")).expect("always a BaseStruct subclass");
55+
let Ok(builder) = cls.getattr(intern!(cls.py(), "__struct_builder__")) else {
56+
// For a retriever-less class
57+
return Ok(Struct::from_raw( StructRaw {
58+
retrievers: vec![],
59+
combiners: vec![],
60+
refs: vec![],
61+
62+
py_type: cls.extract()?,
63+
fully_qualified_name: cls.fully_qualified_name()?.to_string(),
64+
65+
is_compressed: false,
66+
67+
get_ver: get_if_impl(cls, intern!(cls.py(), "_get_version")),
68+
compress: get_if_impl(cls, intern!(cls.py(), "_compress")),
69+
decompress: get_if_impl(cls, intern!(cls.py(), "_decompress")),
70+
}));
71+
};
5772

5873
if builder.is_none() {
5974
return cls

stubs/bfp_rs/combinators/get.pyi

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ class Get:
1313
def __rsub__(self, other: Get | int) -> Get: ...
1414
def __mul__(self, other: Get | int) -> Get: ...
1515
def __rmul__(self, other: Get | int) -> Get: ...
16-
def __div__(self, other: Get | int) -> Get: ...
17-
def __rdiv__(self, other: Get | int) -> Get: ...
16+
def __floordiv__(self, other: Get | int) -> Get: ...
17+
def __rfloordiv__(self, other: Get | int) -> Get: ...
1818
def __mod__(self, other: Get | int) -> Get: ...
1919
def __rmod__(self, other: Get | int) -> Get: ...
2020
def __and__(self, other: Get | int) -> Get: ...

0 commit comments

Comments
 (0)