Skip to content

Commit 713edc5

Browse files
Convert some objstring methods to new style.
1 parent 7f75e3e commit 713edc5

File tree

4 files changed

+93
-74
lines changed

4 files changed

+93
-74
lines changed

vm/src/obj/objbool.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ pub fn boolval(vm: &mut VirtualMachine, obj: PyObjectRef) -> Result<bool, PyObje
1717
PyObjectPayload::Float { value } => value != 0.0,
1818
PyObjectPayload::Sequence { ref elements } => !elements.borrow().is_empty(),
1919
PyObjectPayload::Dict { ref elements } => !elements.borrow().is_empty(),
20-
PyObjectPayload::String { ref value } => !value.is_empty(),
20+
// FIXME
21+
//PyObjectPayload::String { ref value } => !value.is_empty(),
2122
PyObjectPayload::None { .. } => false,
2223
_ => {
2324
if let Ok(f) = vm.get_method(obj.clone(), "__bool__") {

vm/src/obj/objstr.rs

Lines changed: 82 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ use super::objint;
22
use super::objsequence::PySliceableSequence;
33
use super::objtype;
44
use crate::format::{FormatParseError, FormatPart, FormatString};
5+
use crate::function::PyRef;
56
use crate::pyobject::{
6-
PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
7+
OptArg, PyContext, PyFuncArgs, PyIterable, PyObjectPayload, PyObjectPayload2, PyObjectRef,
8+
PyResult, TypeProtocol,
79
};
810
use crate::vm::VirtualMachine;
911
use num_traits::ToPrimitive;
@@ -16,6 +18,74 @@ extern crate unicode_segmentation;
1618

1719
use self::unicode_segmentation::UnicodeSegmentation;
1820

21+
#[derive(Clone, Debug)]
22+
pub struct PyString {
23+
// TODO: shouldn't be public
24+
pub value: String,
25+
}
26+
27+
impl PyString {
28+
pub fn endswith(
29+
zelf: PyRef<Self>,
30+
suffix: PyRef<Self>,
31+
start: OptArg<usize>,
32+
end: OptArg<usize>,
33+
_vm: &mut VirtualMachine,
34+
) -> bool {
35+
let start = start.unwrap_or(0);
36+
let end = end.unwrap_or(zelf.value.len());
37+
zelf.value[start..end].ends_with(&suffix.value)
38+
}
39+
40+
pub fn startswith(
41+
zelf: PyRef<Self>,
42+
prefix: PyRef<Self>,
43+
start: OptArg<usize>,
44+
end: OptArg<usize>,
45+
_vm: &mut VirtualMachine,
46+
) -> bool {
47+
let start = start.unwrap_or(0);
48+
let end = end.unwrap_or(zelf.value.len());
49+
zelf.value[start..end].starts_with(&prefix.value)
50+
}
51+
52+
fn upper(zelf: PyRef<Self>, _vm: &mut VirtualMachine) -> PyString {
53+
PyString {
54+
value: zelf.value.to_uppercase(),
55+
}
56+
}
57+
58+
fn lower(zelf: PyRef<Self>, _vm: &mut VirtualMachine) -> PyString {
59+
PyString {
60+
value: zelf.value.to_lowercase(),
61+
}
62+
}
63+
64+
fn join(
65+
zelf: PyRef<Self>,
66+
iterable: PyIterable<PyRef<Self>>,
67+
vm: &mut VirtualMachine,
68+
) -> PyResult<PyString> {
69+
let mut joined = String::new();
70+
71+
for (idx, elem) in iterable.iter(vm)?.enumerate() {
72+
let elem = elem?;
73+
if idx != 0 {
74+
joined.push_str(&zelf.value);
75+
}
76+
joined.push_str(&elem.value)
77+
}
78+
79+
Ok(PyString { value: joined })
80+
}
81+
}
82+
83+
impl PyObjectPayload2 for PyString {
84+
fn required_type(ctx: &PyContext) -> PyObjectRef {
85+
ctx.str_type()
86+
}
87+
}
88+
1989
pub fn init(context: &PyContext) {
2090
let str_type = &context.str_type;
2191
context.set_attr(&str_type, "__add__", context.new_rustfunc(str_add));
@@ -37,9 +107,9 @@ pub fn init(context: &PyContext) {
37107
context.set_attr(&str_type, "__str__", context.new_rustfunc(str_str));
38108
context.set_attr(&str_type, "__repr__", context.new_rustfunc(str_repr));
39109
context.set_attr(&str_type, "format", context.new_rustfunc(str_format));
40-
context.set_attr(&str_type, "lower", context.new_rustfunc(str_lower));
110+
context.set_attr(&str_type, "lower", context.new_rustfunc(PyString::lower));
41111
context.set_attr(&str_type, "casefold", context.new_rustfunc(str_casefold));
42-
context.set_attr(&str_type, "upper", context.new_rustfunc(str_upper));
112+
context.set_attr(&str_type, "upper", context.new_rustfunc(PyString::upper));
43113
context.set_attr(
44114
&str_type,
45115
"capitalize",
@@ -50,11 +120,15 @@ pub fn init(context: &PyContext) {
50120
context.set_attr(&str_type, "strip", context.new_rustfunc(str_strip));
51121
context.set_attr(&str_type, "lstrip", context.new_rustfunc(str_lstrip));
52122
context.set_attr(&str_type, "rstrip", context.new_rustfunc(str_rstrip));
53-
context.set_attr(&str_type, "endswith", context.new_rustfunc(str_endswith));
123+
context.set_attr(
124+
&str_type,
125+
"endswith",
126+
context.new_rustfunc(PyString::endswith),
127+
);
54128
context.set_attr(
55129
&str_type,
56130
"startswith",
57-
context.new_rustfunc(str_startswith),
131+
context.new_rustfunc(PyString::startswith),
58132
);
59133
context.set_attr(&str_type, "isalnum", context.new_rustfunc(str_isalnum));
60134
context.set_attr(&str_type, "isnumeric", context.new_rustfunc(str_isnumeric));
@@ -74,7 +148,7 @@ pub fn init(context: &PyContext) {
74148
"splitlines",
75149
context.new_rustfunc(str_splitlines),
76150
);
77-
context.set_attr(&str_type, "join", context.new_rustfunc(str_join));
151+
context.set_attr(&str_type, "join", context.new_rustfunc(PyString::join));
78152
context.set_attr(&str_type, "find", context.new_rustfunc(str_find));
79153
context.set_attr(&str_type, "rfind", context.new_rustfunc(str_rfind));
80154
context.set_attr(&str_type, "index", context.new_rustfunc(str_index));
@@ -103,19 +177,11 @@ pub fn init(context: &PyContext) {
103177
}
104178

105179
pub fn get_value(obj: &PyObjectRef) -> String {
106-
if let PyObjectPayload::String { value } = &obj.payload {
107-
value.to_string()
108-
} else {
109-
panic!("Inner error getting str");
110-
}
180+
obj.payload::<PyString>().unwrap().value.clone()
111181
}
112182

113183
pub fn borrow_value(obj: &PyObjectRef) -> &str {
114-
if let PyObjectPayload::String { value } = &obj.payload {
115-
value.as_str()
116-
} else {
117-
panic!("Inner error getting str");
118-
}
184+
&obj.payload::<PyString>().unwrap().value
119185
}
120186

121187
fn str_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -377,18 +443,6 @@ fn str_mul(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
377443
}
378444
}
379445

380-
fn str_upper(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
381-
arg_check!(vm, args, required = [(s, Some(vm.ctx.str_type()))]);
382-
let value = get_value(&s).to_uppercase();
383-
Ok(vm.ctx.new_str(value))
384-
}
385-
386-
fn str_lower(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
387-
arg_check!(vm, args, required = [(s, Some(vm.ctx.str_type()))]);
388-
let value = get_value(&s).to_lowercase();
389-
Ok(vm.ctx.new_str(value))
390-
}
391-
392446
fn str_capitalize(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
393447
arg_check!(vm, args, required = [(s, Some(vm.ctx.str_type()))]);
394448
let value = get_value(&s);
@@ -467,17 +521,6 @@ fn str_rstrip(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
467521
Ok(vm.ctx.new_str(value))
468522
}
469523

470-
fn str_endswith(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
471-
arg_check!(
472-
vm,
473-
args,
474-
required = [(s, Some(vm.ctx.str_type())), (pat, Some(vm.ctx.str_type()))]
475-
);
476-
let value = get_value(&s);
477-
let pat = get_value(&pat);
478-
Ok(vm.ctx.new_bool(value.ends_with(pat.as_str())))
479-
}
480-
481524
fn str_isidentifier(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
482525
arg_check!(vm, args, required = [(s, Some(vm.ctx.str_type()))]);
483526
let value = get_value(&s);
@@ -557,22 +600,6 @@ fn str_zfill(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
557600
Ok(vm.ctx.new_str(new_str))
558601
}
559602

560-
fn str_join(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
561-
arg_check!(
562-
vm,
563-
args,
564-
required = [(s, Some(vm.ctx.str_type())), (iterable, None)]
565-
);
566-
let value = get_value(&s);
567-
let elements: Vec<String> = vm
568-
.extract_elements(iterable)?
569-
.iter()
570-
.map(|w| get_value(&w))
571-
.collect();
572-
let joined = elements.join(&value);
573-
Ok(vm.ctx.new_str(joined))
574-
}
575-
576603
fn str_count(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
577604
arg_check!(
578605
vm,
@@ -862,17 +889,6 @@ fn str_center(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
862889
Ok(vm.ctx.new_str(new_str))
863890
}
864891

865-
fn str_startswith(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
866-
arg_check!(
867-
vm,
868-
args,
869-
required = [(s, Some(vm.ctx.str_type())), (pat, Some(vm.ctx.str_type()))]
870-
);
871-
let value = get_value(&s);
872-
let pat = get_value(&pat);
873-
Ok(vm.ctx.new_bool(value.starts_with(pat.as_str())))
874-
}
875-
876892
fn str_contains(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
877893
arg_check!(
878894
vm,

vm/src/pyobject.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,12 @@ impl PyContext {
480480
}
481481

482482
pub fn new_str(&self, s: String) -> PyObjectRef {
483-
PyObject::new(PyObjectPayload::String { value: s }, self.str_type())
483+
PyObject::new(
484+
PyObjectPayload::AnyRustValue {
485+
value: Box::new(objstr::PyString { value: s }),
486+
},
487+
self.str_type(),
488+
)
484489
}
485490

486491
pub fn new_bytes(&self, data: Vec<u8>) -> PyObjectRef {
@@ -1251,9 +1256,6 @@ py_native_func_factory_tuple!((a, A), (b, B), (c, C), (d, D), (e, E));
12511256
/// of rust data for a particular python object. Determine the python type
12521257
/// by using for example the `.typ()` method on a python object.
12531258
pub enum PyObjectPayload {
1254-
String {
1255-
value: String,
1256-
},
12571259
Integer {
12581260
value: BigInt,
12591261
},
@@ -1357,7 +1359,6 @@ pub enum PyObjectPayload {
13571359
impl fmt::Debug for PyObjectPayload {
13581360
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
13591361
match self {
1360-
PyObjectPayload::String { ref value } => write!(f, "str \"{}\"", value),
13611362
PyObjectPayload::Integer { ref value } => write!(f, "int {}", value),
13621363
PyObjectPayload::Float { ref value } => write!(f, "float {}", value),
13631364
PyObjectPayload::Complex { ref value } => write!(f, "complex {}", value),

vm/src/stdlib/json.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,9 @@ impl<'de> Visitor<'de> for PyObjectDeserializer<'de> {
167167
// than wrapping the given object up and then unwrapping it to determine whether or
168168
// not it is a string
169169
while let Some((key_obj, value)) = access.next_entry_seed(self.clone(), self.clone())? {
170-
let key = match key_obj.payload {
171-
PyObjectPayload::String { ref value } => value.clone(),
170+
let key: String = match key_obj.payload {
171+
// FIXME
172+
// PyObjectPayload::String { ref value } => value.clone(),
172173
_ => unimplemented!("map keys must be strings"),
173174
};
174175
self.vm.ctx.set_item(&dict, &key, value);

0 commit comments

Comments
 (0)