Skip to content

Commit c83eb12

Browse files
authored
Merge pull request RustPython#3258 from youknowone/ascii-buffer
ArgAsciiBuffer
2 parents 621383b + 4a544a3 commit c83eb12

File tree

4 files changed

+53
-67
lines changed

4 files changed

+53
-67
lines changed

Lib/test/test_binascii.py

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -449,16 +449,6 @@ class ArrayBinASCIITest(BinASCIITest):
449449
def type2test(self, s):
450450
return array.array('B', list(s))
451451

452-
# TODO: RUSTPYTHON
453-
@unittest.expectedFailure
454-
def test_crc32(self):
455-
super().test_crc32()
456-
457-
# TODO: RUSTPYTHON
458-
@unittest.expectedFailure
459-
def test_base64valid(self):
460-
super().test_base64valid()
461-
462452

463453
class BytearrayBinASCIITest(BinASCIITest):
464454
type2test = bytearray
@@ -467,15 +457,6 @@ class BytearrayBinASCIITest(BinASCIITest):
467457
class MemoryviewBinASCIITest(BinASCIITest):
468458
type2test = memoryview
469459

470-
# TODO: RUSTPYTHON
471-
@unittest.expectedFailure
472-
def test_crc32(self):
473-
super().test_crc32()
474-
475-
# TODO: RUSTPYTHON
476-
@unittest.expectedFailure
477-
def test_base64valid(self):
478-
super().test_base64valid()
479460

480461
if __name__ == "__main__":
481462
unittest.main()

stdlib/src/binascii.rs

Lines changed: 7 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,52 +3,13 @@ pub(crate) use decl::make_module;
33
#[pymodule(name = "binascii")]
44
mod decl {
55
use crate::vm::{
6-
builtins::{PyByteArray, PyBytes, PyStr, PyTypeRef},
7-
function::{ArgBytesLike, OptionalArg},
8-
match_class, PyObjectRef, PyRef, PyResult, TryFromObject, TypeProtocol, VirtualMachine,
6+
builtins::PyTypeRef,
7+
function::{ArgAsciiBuffer, ArgBytesLike, OptionalArg},
8+
PyResult, VirtualMachine,
99
};
1010
use crc::{crc32, Hasher32};
1111
use itertools::Itertools;
1212

13-
enum SerializedData {
14-
Bytes(PyRef<PyBytes>),
15-
Buffer(PyRef<PyByteArray>),
16-
Ascii(PyRef<PyStr>),
17-
}
18-
19-
impl TryFromObject for SerializedData {
20-
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
21-
match_class!(match obj {
22-
b @ PyBytes => Ok(SerializedData::Bytes(b)),
23-
b @ PyByteArray => Ok(SerializedData::Buffer(b)),
24-
a @ PyStr => {
25-
if a.as_str().is_ascii() {
26-
Ok(SerializedData::Ascii(a))
27-
} else {
28-
Err(vm.new_value_error(
29-
"string argument should contain only ASCII characters".to_owned(),
30-
))
31-
}
32-
}
33-
obj => Err(vm.new_type_error(format!(
34-
"argument should be bytes, buffer or ASCII string, not '{}'",
35-
obj.class().name(),
36-
))),
37-
})
38-
}
39-
}
40-
41-
impl SerializedData {
42-
#[inline]
43-
pub fn with_ref<R>(&self, f: impl FnOnce(&[u8]) -> R) -> R {
44-
match self {
45-
SerializedData::Bytes(b) => f(b.as_bytes()),
46-
SerializedData::Buffer(b) => f(&b.borrow_buf()),
47-
SerializedData::Ascii(a) => f(a.as_str().as_bytes()),
48-
}
49-
}
50-
}
51-
5213
#[pyattr(name = "Error")]
5314
fn error_type(vm: &VirtualMachine) -> PyTypeRef {
5415
rustpython_common::static_cell! {
@@ -113,7 +74,7 @@ mod decl {
11374

11475
#[pyfunction(name = "a2b_hex")]
11576
#[pyfunction]
116-
fn unhexlify(data: SerializedData, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
77+
fn unhexlify(data: ArgAsciiBuffer, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
11778
data.with_ref(|hex_bytes| {
11879
if hex_bytes.len() % 2 != 0 {
11980
return Err(vm.new_value_error("Odd-length string".to_owned()));
@@ -133,7 +94,7 @@ mod decl {
13394
}
13495

13596
#[pyfunction]
136-
fn crc32(data: SerializedData, value: OptionalArg<u32>, vm: &VirtualMachine) -> PyResult {
97+
fn crc32(data: ArgBytesLike, value: OptionalArg<u32>, vm: &VirtualMachine) -> PyResult {
13798
let crc = value.unwrap_or(0);
13899

139100
let mut digest = crc32::Digest::new_with_initial(crc32::IEEE, crc);
@@ -149,7 +110,7 @@ mod decl {
149110
}
150111

151112
#[pyfunction]
152-
fn a2b_base64(s: SerializedData, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
113+
fn a2b_base64(s: ArgAsciiBuffer, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
153114
s.with_ref(|b| {
154115
let mut buf;
155116
let b = if memchr::memchr(b'\n', b).is_some() {
@@ -190,7 +151,7 @@ mod decl {
190151
}
191152

192153
#[pyfunction]
193-
fn a2b_uu(s: SerializedData, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
154+
fn a2b_uu(s: ArgAsciiBuffer, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
194155
s.with_ref(|b| {
195156
// First byte: binary data length (in bytes)
196157
let length = if b.is_empty() {

vm/src/function.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use std::marker::PhantomData;
1414
use std::ops::RangeInclusive;
1515

1616
pub use argument::{ArgCallable, ArgIterable};
17-
pub use buffer::{ArgBytesLike, ArgMemoryBuffer, ArgStrOrBytesLike};
17+
pub use buffer::{ArgAsciiBuffer, ArgBytesLike, ArgMemoryBuffer, ArgStrOrBytesLike};
1818
pub use number::{ArgIntoBool, ArgIntoComplex, ArgIntoFloat};
1919

2020
/// Implemented by any type that can be returned from a built-in Python function.

vm/src/function/buffer.rs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::{
2-
builtins::PyStrRef,
2+
builtins::{PyStr, PyStrRef},
33
common::borrow::{BorrowedValue, BorrowedValueMut},
44
protocol::PyBuffer,
55
PyObjectRef, PyResult, TryFromBorrowedObject, TryFromObject, VirtualMachine,
@@ -146,3 +146,47 @@ impl ArgStrOrBytesLike {
146146
}
147147
}
148148
}
149+
150+
#[derive(Debug)]
151+
pub enum ArgAsciiBuffer {
152+
String(PyStrRef),
153+
Buffer(ArgBytesLike),
154+
}
155+
156+
impl TryFromObject for ArgAsciiBuffer {
157+
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
158+
match obj.downcast::<PyStr>() {
159+
Ok(string) => {
160+
if string.as_str().is_ascii() {
161+
Ok(ArgAsciiBuffer::String(string))
162+
} else {
163+
Err(vm.new_value_error(
164+
"string argument should contain only ASCII characters".to_owned(),
165+
))
166+
}
167+
}
168+
Err(obj) => ArgBytesLike::try_from_object(vm, obj).map(ArgAsciiBuffer::Buffer),
169+
}
170+
}
171+
}
172+
173+
impl ArgAsciiBuffer {
174+
pub fn len(&self) -> usize {
175+
match self {
176+
Self::String(s) => s.as_str().len(),
177+
Self::Buffer(buffer) => buffer.len(),
178+
}
179+
}
180+
181+
pub fn is_empty(&self) -> bool {
182+
self.len() == 0
183+
}
184+
185+
#[inline]
186+
pub fn with_ref<R>(&self, f: impl FnOnce(&[u8]) -> R) -> R {
187+
match self {
188+
Self::String(s) => f(s.as_str().as_bytes()),
189+
Self::Buffer(buffer) => buffer.with_ref(f),
190+
}
191+
}
192+
}

0 commit comments

Comments
 (0)