From 4a000c424c66c27c4f6318622de2817abb82da23 Mon Sep 17 00:00:00 2001 From: Joey Date: Wed, 6 Mar 2019 19:53:03 -0800 Subject: [PATCH] Improvements to OptionalArg extractor --- vm/src/obj/objstr.rs | 20 ++++++++++---------- vm/src/pyobject.rs | 29 +++++++++++++++++++---------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/vm/src/obj/objstr.rs b/vm/src/obj/objstr.rs index 4ee7f38f5..6d9d622d0 100644 --- a/vm/src/obj/objstr.rs +++ b/vm/src/obj/objstr.rs @@ -4,8 +4,8 @@ use super::objtype; use crate::format::{FormatParseError, FormatPart, FormatString}; use crate::function::PyRef; use crate::pyobject::{ - IntoPyObject, OptArg, PyContext, PyFuncArgs, PyIterable, PyObjectPayload, PyObjectPayload2, - PyObjectRef, PyResult, TypeProtocol, + IntoPyObject, OptionalArg, PyContext, PyFuncArgs, PyIterable, PyObjectPayload, + PyObjectPayload2, PyObjectRef, PyResult, TypeProtocol, }; use crate::vm::VirtualMachine; use num_traits::ToPrimitive; @@ -160,24 +160,24 @@ impl PyStringRef { fn endswith( self, suffix: PyStringRef, - start: OptArg, - end: OptArg, + start: OptionalArg, + end: OptionalArg, _vm: &mut VirtualMachine, ) -> bool { - let start = start.unwrap_or(0); - let end = end.unwrap_or(self.value.len()); + let start = start.into_option().unwrap_or(0); + let end = end.into_option().unwrap_or(self.value.len()); self.value[start..end].ends_with(&suffix.value) } fn startswith( self, prefix: PyStringRef, - start: OptArg, - end: OptArg, + start: OptionalArg, + end: OptionalArg, _vm: &mut VirtualMachine, ) -> bool { - let start = start.unwrap_or(0); - let end = end.unwrap_or(self.value.len()); + let start = start.into_option().unwrap_or(0); + let end = end.into_option().unwrap_or(self.value.len()); self.value[start..end].starts_with(&prefix.value) } diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 6a618cd7b..925c56481 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -1212,17 +1212,26 @@ where } } -pub struct OptArg(Option); +/// An argument that may or may not be provided by the caller. +/// +/// This style of argument is not possible in pure Python. +pub enum OptionalArg { + Present(T), + Missing, +} -impl std::ops::Deref for OptArg { - type Target = Option; +use self::OptionalArg::*; - fn deref(&self) -> &Option { - &self.0 +impl OptionalArg { + pub fn into_option(self) -> Option { + match self { + Present(value) => Some(value), + Missing => None, + } } } -impl FromArgs for OptArg +impl FromArgs for OptionalArg where T: TryFromObject, { @@ -1237,16 +1246,16 @@ where where I: Iterator, { - Ok(OptArg(if let Some(PyArg::Positional(_)) = args.peek() { + Ok(if let Some(PyArg::Positional(_)) = args.peek() { let value = if let Some(PyArg::Positional(value)) = args.next() { value } else { unreachable!() }; - Some(T::try_from_object(vm, value)?) + Present(T::try_from_object(vm, value)?) } else { - None - })) + Missing + }) } }