(
zelf: PyRef<Self>,
PyDequeOptions { iterable, maxlen }: Self::Args,
vm: &VirtualMachine,
)
| 419 | type Args = PyDequeOptions; |
| 420 | |
| 421 | fn init( |
| 422 | zelf: PyRef<Self>, |
| 423 | PyDequeOptions { iterable, maxlen }: Self::Args, |
| 424 | vm: &VirtualMachine, |
| 425 | ) -> PyResult<()> { |
| 426 | // TODO: This is _basically_ pyobject_to_opt_usize in itertools.rs |
| 427 | // need to move that function elsewhere and refactor usages. |
| 428 | let maxlen = if let Some(obj) = maxlen.into_option() { |
| 429 | if !vm.is_none(&obj) { |
| 430 | let maxlen: isize = obj |
| 431 | .downcast_ref::<PyInt>() |
| 432 | .ok_or_else(|| vm.new_type_error("an integer is required."))? |
| 433 | .try_to_primitive(vm)?; |
| 434 | |
| 435 | if maxlen.is_negative() { |
| 436 | return Err(vm.new_value_error("maxlen must be non-negative.")); |
| 437 | } |
| 438 | Some(maxlen as usize) |
| 439 | } else { |
| 440 | None |
| 441 | } |
| 442 | } else { |
| 443 | None |
| 444 | }; |
| 445 | |
| 446 | // retrieve elements first to not to make too huge lock |
| 447 | let elements = iterable |
| 448 | .into_option() |
| 449 | .map(|iter| { |
| 450 | let mut elements: Vec<PyObjectRef> = iter.try_to_value(vm)?; |
| 451 | if let Some(maxlen) = maxlen { |
| 452 | elements.drain(..elements.len().saturating_sub(maxlen)); |
| 453 | } |
| 454 | Ok(elements) |
| 455 | }) |
| 456 | .transpose()?; |
| 457 | |
| 458 | // SAFETY: This is hacky part for read-only field |
| 459 | // Because `maxlen` is only mutated from __init__. We can abuse the lock of deque to ensure this is locked enough. |
| 460 | // If we make a single lock of deque not only for extend but also for setting maxlen, it will be safe. |
| 461 | { |
| 462 | let mut deque = zelf.borrow_deque_mut(); |
| 463 | // Clear any previous data present. |
| 464 | deque.clear(); |
| 465 | unsafe { |
| 466 | // `maxlen` is better to be defined as UnsafeCell in common practice, |
| 467 | // but then more type works without any safety benefits |
| 468 | let unsafe_maxlen = |
| 469 | &zelf.maxlen as *const _ as *const core::cell::UnsafeCell<Option<usize>>; |
| 470 | *(*unsafe_maxlen).get() = maxlen; |
| 471 | } |
| 472 | if let Some(elements) = elements { |
| 473 | deque.extend(elements); |
| 474 | } |
| 475 | } |
| 476 | |
| 477 | Ok(()) |
| 478 | } |
nothing calls this directly
no test coverage detected