Implement full SSD1306 OLED display support: - Splash screen on boot (1.5s) with project name, version, board - Dashboard showing radio state, config, counters, RSSI/SNR - RSSI history sparkline (64-sample ring buffer, 2px-wide bars) - DisplayOn/DisplayOff host commands routed via dedicated channel - Pure render functions against generic DrawTarget (no hardware coupling) - Display on/off control bypasses radio task entirely Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
4957 lines
85 KiB
Rust
4957 lines
85 KiB
Rust
use super::*;
|
|
use snapbox::prelude::*;
|
|
use snapbox::str;
|
|
|
|
use crate::error::ErrMode;
|
|
use crate::error::ErrMode::Backtrack;
|
|
use crate::error::InputError;
|
|
use crate::token::literal;
|
|
|
|
#[test]
|
|
fn test_literal_support_char() {
|
|
assert_eq!(
|
|
literal::<_, &[u8], ErrMode<InputError<_>>>(Caseless('a')).parse_peek(b"ABCxyz"),
|
|
Ok((&b"BCxyz"[..], &b"A"[..]))
|
|
);
|
|
|
|
assert_eq!(
|
|
literal::<_, &[u8], ErrMode<InputError<_>>>('a').parse_peek(b"ABCxyz"),
|
|
Err(Backtrack(InputError::at(&b"ABCxyz"[..],)))
|
|
);
|
|
|
|
assert_eq!(
|
|
literal::<_, &[u8], ErrMode<InputError<_>>>(Caseless('π')).parse_peek(b"\xCF\x803.14"),
|
|
Ok((&b"3.14"[..], "π".as_bytes()))
|
|
);
|
|
|
|
assert_eq!(
|
|
literal::<_, _, ErrMode<InputError<_>>>(Caseless('🧑')).parse_peek("🧑你好"),
|
|
Ok(("你好", "🧑"))
|
|
);
|
|
|
|
let mut buffer = [0; 4];
|
|
let input = '\u{241b}'.encode_utf8(&mut buffer);
|
|
assert_eq!(
|
|
literal::<_, &[u8], ErrMode<InputError<_>>>(Caseless('␛')).parse_peek(input.as_bytes()),
|
|
Ok((&b""[..], [226, 144, 155].as_slice()))
|
|
);
|
|
}
|
|
|
|
mod complete {
|
|
use super::*;
|
|
|
|
use proptest::prelude::*;
|
|
|
|
use crate::combinator::alt;
|
|
use crate::error::ErrMode;
|
|
use crate::error::InputError;
|
|
use crate::prelude::*;
|
|
use crate::stream::ParseSlice;
|
|
use crate::token::none_of;
|
|
use crate::token::one_of;
|
|
use crate::token::take_till;
|
|
#[cfg(feature = "alloc")]
|
|
use alloc::string::String;
|
|
#[cfg(feature = "alloc")]
|
|
use alloc::vec::Vec;
|
|
|
|
#[test]
|
|
fn character() {
|
|
let a: &[u8] = b"abcd";
|
|
let b: &[u8] = b"1234";
|
|
let c: &[u8] = b"a123";
|
|
let d: &[u8] = "azé12".as_bytes();
|
|
let e: &[u8] = b" ";
|
|
let f: &[u8] = b" ;";
|
|
//assert_parse!(alpha1::<_, InputError>(a), str![]);
|
|
assert_parse!(
|
|
alpha1.parse_peek(a),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[],
|
|
[
|
|
97,
|
|
98,
|
|
99,
|
|
100,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
alpha1.parse_peek(b),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
49,
|
|
50,
|
|
51,
|
|
52,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
alpha1.parse_peek(c),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
49,
|
|
50,
|
|
51,
|
|
],
|
|
[
|
|
97,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
alpha1.parse_peek(d),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
195,
|
|
169,
|
|
49,
|
|
50,
|
|
],
|
|
[
|
|
97,
|
|
122,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
digit1.parse_peek(a),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
97,
|
|
98,
|
|
99,
|
|
100,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
digit1.parse_peek(b),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[],
|
|
[
|
|
49,
|
|
50,
|
|
51,
|
|
52,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
digit1.parse_peek(c),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
97,
|
|
49,
|
|
50,
|
|
51,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
digit1.parse_peek(d),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
97,
|
|
122,
|
|
195,
|
|
169,
|
|
49,
|
|
50,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(a),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[],
|
|
[
|
|
97,
|
|
98,
|
|
99,
|
|
100,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(b),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[],
|
|
[
|
|
49,
|
|
50,
|
|
51,
|
|
52,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(c),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[],
|
|
[
|
|
97,
|
|
49,
|
|
50,
|
|
51,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(d),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
122,
|
|
195,
|
|
169,
|
|
49,
|
|
50,
|
|
],
|
|
[
|
|
97,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(e),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
32,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
oct_digit1.parse_peek(a),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
97,
|
|
98,
|
|
99,
|
|
100,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
oct_digit1.parse_peek(b),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[],
|
|
[
|
|
49,
|
|
50,
|
|
51,
|
|
52,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
oct_digit1.parse_peek(c),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
97,
|
|
49,
|
|
50,
|
|
51,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
oct_digit1.parse_peek(d),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
97,
|
|
122,
|
|
195,
|
|
169,
|
|
49,
|
|
50,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
alphanumeric1.parse_peek(a),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[],
|
|
[
|
|
97,
|
|
98,
|
|
99,
|
|
100,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
//assert_parse!(fix_error!(b,(), alphanumeric), str![]);
|
|
assert_parse!(
|
|
alphanumeric1.parse_peek(c),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[],
|
|
[
|
|
97,
|
|
49,
|
|
50,
|
|
51,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
alphanumeric1.parse_peek(d),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
195,
|
|
169,
|
|
49,
|
|
50,
|
|
],
|
|
[
|
|
97,
|
|
122,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
space1.parse_peek(e),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[],
|
|
[
|
|
32,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
space1.parse_peek(f),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
[
|
|
32,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[cfg(feature = "alloc")]
|
|
#[test]
|
|
fn character_s() {
|
|
let a = "abcd";
|
|
let b = "1234";
|
|
let c = "a123";
|
|
let d = "azé12";
|
|
let e = " ";
|
|
assert_parse!(
|
|
alpha1.parse_peek(a),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"",
|
|
"abcd",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
alpha1.parse_peek(b),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: "1234",
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
alpha1.parse_peek(c),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"123",
|
|
"a",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
alpha1.parse_peek(d),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"é12",
|
|
"az",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
digit1.parse_peek(a),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: "abcd",
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
digit1.parse_peek(b),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"",
|
|
"1234",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
digit1.parse_peek(c),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: "a123",
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
digit1.parse_peek(d),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: "azé12",
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(a),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"",
|
|
"abcd",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(b),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"",
|
|
"1234",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(c),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"",
|
|
"a123",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(d),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"zé12",
|
|
"a",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(e),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: " ",
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
oct_digit1.parse_peek(a),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: "abcd",
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
oct_digit1.parse_peek(b),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"",
|
|
"1234",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
oct_digit1.parse_peek(c),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: "a123",
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
oct_digit1.parse_peek(d),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: "azé12",
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
alphanumeric1.parse_peek(a),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"",
|
|
"abcd",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
//assert_parse!(fix_error!(b,(), alphanumeric), str![]);
|
|
assert_parse!(
|
|
alphanumeric1.parse_peek(c),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"",
|
|
"a123",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
alphanumeric1.parse_peek(d),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"é12",
|
|
"az",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
space1.parse_peek(e),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"",
|
|
" ",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
use crate::stream::Offset;
|
|
#[test]
|
|
fn offset() {
|
|
let a = &b"abcd;"[..];
|
|
let b = &b"1234;"[..];
|
|
let c = &b"a123;"[..];
|
|
let d = &b" \t;"[..];
|
|
let e = &b" \t\r\n;"[..];
|
|
let f = &b"123abcDEF;"[..];
|
|
|
|
match alpha1::<_, InputError<_>>.parse_peek(a) {
|
|
Ok((i, _)) => {
|
|
assert_eq!(i.offset_from(&a) + i.len(), a.len());
|
|
}
|
|
_ => panic!("wrong return type in offset test for alpha"),
|
|
}
|
|
match digit1::<_, InputError<_>>.parse_peek(b) {
|
|
Ok((i, _)) => {
|
|
assert_eq!(i.offset_from(&b) + i.len(), b.len());
|
|
}
|
|
_ => panic!("wrong return type in offset test for digit"),
|
|
}
|
|
match alphanumeric1::<_, InputError<_>>.parse_peek(c) {
|
|
Ok((i, _)) => {
|
|
assert_eq!(i.offset_from(&c) + i.len(), c.len());
|
|
}
|
|
_ => panic!("wrong return type in offset test for alphanumeric"),
|
|
}
|
|
match space1::<_, InputError<_>>.parse_peek(d) {
|
|
Ok((i, _)) => {
|
|
assert_eq!(i.offset_from(&d) + i.len(), d.len());
|
|
}
|
|
_ => panic!("wrong return type in offset test for space"),
|
|
}
|
|
match multispace1::<_, InputError<_>>.parse_peek(e) {
|
|
Ok((i, _)) => {
|
|
assert_eq!(i.offset_from(&e) + i.len(), e.len());
|
|
}
|
|
_ => panic!("wrong return type in offset test for multispace"),
|
|
}
|
|
match hex_digit1::<_, InputError<_>>.parse_peek(f) {
|
|
Ok((i, _)) => {
|
|
assert_eq!(i.offset_from(&f) + i.len(), f.len());
|
|
}
|
|
_ => panic!("wrong return type in offset test for hex_digit"),
|
|
}
|
|
match oct_digit1::<_, InputError<_>>.parse_peek(f) {
|
|
Ok((i, _)) => {
|
|
assert_eq!(i.offset_from(&f) + i.len(), f.len());
|
|
}
|
|
_ => panic!("wrong return type in offset test for oct_digit"),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn is_till_line_ending_bytes() {
|
|
let a: &[u8] = b"ab12cd\nefgh";
|
|
assert_parse!(
|
|
till_line_ending.parse_peek(a),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
10,
|
|
101,
|
|
102,
|
|
103,
|
|
104,
|
|
],
|
|
[
|
|
97,
|
|
98,
|
|
49,
|
|
50,
|
|
99,
|
|
100,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
let b: &[u8] = b"ab12cd\nefgh\nijkl";
|
|
assert_parse!(
|
|
till_line_ending.parse_peek(b),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
10,
|
|
101,
|
|
102,
|
|
103,
|
|
104,
|
|
10,
|
|
105,
|
|
106,
|
|
107,
|
|
108,
|
|
],
|
|
[
|
|
97,
|
|
98,
|
|
49,
|
|
50,
|
|
99,
|
|
100,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
let c: &[u8] = b"ab12cd\r\nefgh\nijkl";
|
|
assert_parse!(
|
|
till_line_ending.parse_peek(c),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
13,
|
|
10,
|
|
101,
|
|
102,
|
|
103,
|
|
104,
|
|
10,
|
|
105,
|
|
106,
|
|
107,
|
|
108,
|
|
],
|
|
[
|
|
97,
|
|
98,
|
|
49,
|
|
50,
|
|
99,
|
|
100,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
let d: &[u8] = b"ab12cd";
|
|
assert_parse!(
|
|
till_line_ending.parse_peek(d),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[],
|
|
[
|
|
97,
|
|
98,
|
|
49,
|
|
50,
|
|
99,
|
|
100,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn is_till_line_ending_str() {
|
|
let f = "βèƒôřè\rÂßÇáƒƭèř";
|
|
assert_parse!(
|
|
till_line_ending.parse_peek(f),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: "\rÂßÇáƒƭèř",
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
let g2: &str = "ab12cd";
|
|
assert_parse!(
|
|
till_line_ending.parse_peek(g2),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"",
|
|
"ab12cd",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn hex_digit_test() {
|
|
let i = &b"0123456789abcdefABCDEF;"[..];
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(i),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
[
|
|
48,
|
|
49,
|
|
50,
|
|
51,
|
|
52,
|
|
53,
|
|
54,
|
|
55,
|
|
56,
|
|
57,
|
|
97,
|
|
98,
|
|
99,
|
|
100,
|
|
101,
|
|
102,
|
|
65,
|
|
66,
|
|
67,
|
|
68,
|
|
69,
|
|
70,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
let i = &b"g"[..];
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(i),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
103,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
let i = &b"G"[..];
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(i),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
71,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
assert!(AsChar::is_hex_digit(b'0'));
|
|
assert!(AsChar::is_hex_digit(b'9'));
|
|
assert!(AsChar::is_hex_digit(b'a'));
|
|
assert!(AsChar::is_hex_digit(b'f'));
|
|
assert!(AsChar::is_hex_digit(b'A'));
|
|
assert!(AsChar::is_hex_digit(b'F'));
|
|
assert!(!AsChar::is_hex_digit(b'g'));
|
|
assert!(!AsChar::is_hex_digit(b'G'));
|
|
assert!(!AsChar::is_hex_digit(b'/'));
|
|
assert!(!AsChar::is_hex_digit(b':'));
|
|
assert!(!AsChar::is_hex_digit(b'@'));
|
|
assert!(!AsChar::is_hex_digit(b'\x60'));
|
|
}
|
|
|
|
#[test]
|
|
fn oct_digit_test() {
|
|
let i = &b"01234567;"[..];
|
|
assert_parse!(
|
|
oct_digit1.parse_peek(i),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
[
|
|
48,
|
|
49,
|
|
50,
|
|
51,
|
|
52,
|
|
53,
|
|
54,
|
|
55,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
let i = &b"8"[..];
|
|
assert_parse!(
|
|
oct_digit1.parse_peek(i),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
56,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
assert!(AsChar::is_oct_digit(b'0'));
|
|
assert!(AsChar::is_oct_digit(b'7'));
|
|
assert!(!AsChar::is_oct_digit(b'8'));
|
|
assert!(!AsChar::is_oct_digit(b'9'));
|
|
assert!(!AsChar::is_oct_digit(b'a'));
|
|
assert!(!AsChar::is_oct_digit(b'A'));
|
|
assert!(!AsChar::is_oct_digit(b'/'));
|
|
assert!(!AsChar::is_oct_digit(b':'));
|
|
assert!(!AsChar::is_oct_digit(b'@'));
|
|
assert!(!AsChar::is_oct_digit(b'\x60'));
|
|
}
|
|
|
|
#[test]
|
|
fn full_line_windows() {
|
|
#[allow(clippy::type_complexity)]
|
|
fn take_full_line<'i>(i: &mut &'i [u8]) -> TestResult<&'i [u8], (&'i [u8], &'i [u8])> {
|
|
(till_line_ending, line_ending).parse_next(i)
|
|
}
|
|
let input = b"abc\r\n";
|
|
let output = take_full_line.parse_peek(input);
|
|
assert_parse!(
|
|
output,
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[],
|
|
(
|
|
[
|
|
97,
|
|
98,
|
|
99,
|
|
],
|
|
[
|
|
13,
|
|
10,
|
|
],
|
|
),
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn full_line_unix() {
|
|
#[allow(clippy::type_complexity)]
|
|
fn take_full_line<'i>(i: &mut &'i [u8]) -> TestResult<&'i [u8], (&'i [u8], &'i [u8])> {
|
|
(till_line_ending, line_ending).parse_next(i)
|
|
}
|
|
let input = b"abc\n";
|
|
let output = take_full_line.parse_peek(input);
|
|
assert_parse!(
|
|
output,
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[],
|
|
(
|
|
[
|
|
97,
|
|
98,
|
|
99,
|
|
],
|
|
[
|
|
10,
|
|
],
|
|
),
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn check_windows_lineending() {
|
|
let input = b"\r\n";
|
|
let output = line_ending.parse_peek(&input[..]);
|
|
assert_parse!(
|
|
output,
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[],
|
|
[
|
|
13,
|
|
10,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn check_unix_lineending() {
|
|
let input = b"\n";
|
|
let output = line_ending.parse_peek(&input[..]);
|
|
assert_parse!(
|
|
output,
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[],
|
|
[
|
|
10,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn cr_lf() {
|
|
assert_parse!(
|
|
crlf.parse_peek(&b"\r\na"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
97,
|
|
],
|
|
[
|
|
13,
|
|
10,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
crlf.parse_peek(&b"\r"[..]),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
13,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
crlf.parse_peek(&b"\ra"[..]),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
13,
|
|
97,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
assert_parse!(
|
|
crlf.parse_peek("\r\na"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"a",
|
|
"\r\n",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
crlf.parse_peek("\r"),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: "\r",
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
crlf.parse_peek("\ra"),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: "\ra",
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn end_of_line() {
|
|
assert_parse!(
|
|
line_ending.parse_peek(&b"\na"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
97,
|
|
],
|
|
[
|
|
10,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
line_ending.parse_peek(&b"\r\na"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
97,
|
|
],
|
|
[
|
|
13,
|
|
10,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
line_ending.parse_peek(&b"\r"[..]),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
13,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
line_ending.parse_peek(&b"\ra"[..]),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
13,
|
|
97,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
assert_parse!(
|
|
line_ending.parse_peek("\na"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"a",
|
|
"\n",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
line_ending.parse_peek("\r\na"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"a",
|
|
"\r\n",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
line_ending.parse_peek("\r"),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: "\r",
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
line_ending.parse_peek("\ra"),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: "\ra",
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn dec_uint_tests() {
|
|
fn dec_u32<'i>(input: &mut &'i [u8]) -> TestResult<&'i [u8], u32> {
|
|
dec_uint.parse_next(input)
|
|
}
|
|
|
|
assert_parse!(
|
|
dec_u32.parse_peek(&b";"[..]),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
59,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
dec_u32.parse_peek(&b"0;"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
0,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
dec_u32.parse_peek(&b"1;"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
1,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
dec_u32.parse_peek(&b"32;"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
32,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
dec_u32.parse_peek(&b"1000000000000000000000;"[..]), // overflow
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
49,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
59,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn dec_int_tests() {
|
|
fn dec_i32<'i>(input: &mut &'i [u8]) -> TestResult<&'i [u8], i32> {
|
|
dec_int.parse_next(input)
|
|
}
|
|
|
|
assert_parse!(
|
|
dec_i32.parse_peek(&b";"[..]),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
59,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
dec_i32.parse_peek(&b"0;"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
0,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
dec_i32.parse_peek(&b"1;"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
1,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
dec_i32.parse_peek(&b"32;"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
32,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
dec_i32.parse_peek(&b"-0;"[..]),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
45,
|
|
48,
|
|
59,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
dec_i32.parse_peek(&b"-1;"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
-1,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
dec_i32.parse_peek(&b"-32;"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
-32,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
dec_i32.parse_peek(&b"1000000000000000000000;"[..]), // overflow
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
49,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
48,
|
|
59,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn hex_uint_tests() {
|
|
fn hex_u32<'i>(input: &mut &'i [u8]) -> TestResult<&'i [u8], u32> {
|
|
hex_uint.parse_next(input)
|
|
}
|
|
|
|
assert_parse!(
|
|
hex_u32.parse_peek(&b";"[..]),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
59,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_u32.parse_peek(&b"ff;"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
255,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_u32.parse_peek(&b"1be2;"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
7138,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_u32.parse_peek(&b"c5a31be2;"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
3315801058,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_u32.parse_peek(&b"C5A31be2;"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
3315801058,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_u32.parse_peek(&b"00c5a31be2;"[..]), // overflow
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
48,
|
|
48,
|
|
99,
|
|
53,
|
|
97,
|
|
51,
|
|
49,
|
|
98,
|
|
101,
|
|
50,
|
|
59,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_u32.parse_peek(&b"c5a31be201;"[..]), // overflow
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
99,
|
|
53,
|
|
97,
|
|
51,
|
|
49,
|
|
98,
|
|
101,
|
|
50,
|
|
48,
|
|
49,
|
|
59,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_u32.parse_peek(&b"ffffffff;"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
4294967295,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_u32.parse_peek(&b"ffffffffffffffff;"[..]), // overflow
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
59,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_u32.parse_peek(&b"ffffffffffffffff"[..]), // overflow
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_u32.parse_peek(&b"0x1be2;"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
120,
|
|
49,
|
|
98,
|
|
101,
|
|
50,
|
|
59,
|
|
],
|
|
0,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_u32.parse_peek(&b"12af"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[],
|
|
4783,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[cfg(feature = "std")]
|
|
fn float_test() {
|
|
let test_cases = [
|
|
"+3.14",
|
|
"3.14",
|
|
"-3.14",
|
|
"0",
|
|
"0.0",
|
|
"1.",
|
|
".789",
|
|
"-.5",
|
|
"1e7",
|
|
"-1E-7",
|
|
".3e-2",
|
|
"1.e4",
|
|
"1.2e4",
|
|
"12.34",
|
|
"-1.234E-12",
|
|
"-1.234e-12",
|
|
"0.00000000000000000087",
|
|
"inf",
|
|
"Inf",
|
|
"infinity",
|
|
"Infinity",
|
|
"-inf",
|
|
"-Inf",
|
|
"-infinity",
|
|
"-Infinity",
|
|
"+inf",
|
|
"+Inf",
|
|
"+infinity",
|
|
"+Infinity",
|
|
];
|
|
|
|
for test in test_cases {
|
|
let expected32 = str::parse::<f32>(test).unwrap();
|
|
let expected64 = str::parse::<f64>(test).unwrap();
|
|
|
|
println!("now parsing: {test} -> {expected32}");
|
|
|
|
assert_eq!(
|
|
float::<_, _, InputError<_>>.parse_peek(test.as_bytes()),
|
|
Ok((&b""[..], expected32))
|
|
);
|
|
assert_eq!(
|
|
float::<_, _, InputError<_>>.parse_peek(test),
|
|
Ok(("", expected32))
|
|
);
|
|
|
|
assert_eq!(
|
|
float::<_, _, InputError<_>>.parse_peek(test.as_bytes()),
|
|
Ok((&b""[..], expected64))
|
|
);
|
|
assert_eq!(
|
|
float::<_, _, InputError<_>>.parse_peek(test),
|
|
Ok(("", expected64))
|
|
);
|
|
}
|
|
|
|
let remaining_exponent = "-1.234E-";
|
|
assert_parse!(
|
|
float::<_, f64, _>.parse_peek(remaining_exponent),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: "",
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
let nan_test_cases = ["nan", "NaN", "NAN"];
|
|
|
|
for test in nan_test_cases {
|
|
println!("now parsing: {test}");
|
|
|
|
let (remaining, parsed) = float::<_, f32, ()>.parse_peek(test.as_bytes()).unwrap();
|
|
assert!(parsed.is_nan());
|
|
assert!(remaining.is_empty());
|
|
|
|
let (remaining, parsed) = float::<_, f32, ()>.parse_peek(test).unwrap();
|
|
assert!(parsed.is_nan());
|
|
assert!(remaining.is_empty());
|
|
|
|
let (remaining, parsed) = float::<_, f64, ()>.parse_peek(test.as_bytes()).unwrap();
|
|
assert!(parsed.is_nan());
|
|
assert!(remaining.is_empty());
|
|
|
|
let (remaining, parsed) = float::<_, f64, ()>.parse_peek(test).unwrap();
|
|
assert!(parsed.is_nan());
|
|
assert!(remaining.is_empty());
|
|
}
|
|
}
|
|
|
|
proptest! {
|
|
#[test]
|
|
#[cfg(feature = "std")]
|
|
#[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
|
|
fn floats(s in "\\PC*") {
|
|
println!("testing {s}");
|
|
let res1 = parse_f64.parse_peek(&s);
|
|
let res2 = float::<_, f64, ErrMode<()>>.parse_peek(s.as_str());
|
|
assert_eq!(res1, res2);
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "std")]
|
|
fn parse_f64(i: &mut &str) -> ModalResult<f64, ()> {
|
|
match take_float_or_exceptions.parse_next(i) {
|
|
Err(e) => Err(e),
|
|
Ok(s) => {
|
|
if s.is_empty() {
|
|
return Err(ErrMode::Backtrack(()));
|
|
}
|
|
match s.parse_slice() {
|
|
Some(n) => Ok(n),
|
|
None => Err(ErrMode::Backtrack(())),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// issue #1336 "take_escaped hangs if normal parser accepts empty"
|
|
#[test]
|
|
#[cfg_attr(debug_assertions, should_panic)]
|
|
fn complete_take_escaped_hang_1() {
|
|
// issue #1336 "take_escaped hangs if normal parser accepts empty"
|
|
fn escaped_string<'i>(input: &mut &'i str) -> TestResult<&'i str, &'i str> {
|
|
use crate::ascii::alpha0;
|
|
use crate::token::one_of;
|
|
take_escaped(alpha0, '\\', one_of(['n'])).parse_next(input)
|
|
}
|
|
|
|
let input = "7";
|
|
assert_parse!(
|
|
escaped_string.parse_peek(input),
|
|
str![[r#"
|
|
Err(
|
|
Cut(
|
|
InputError {
|
|
input: "7",
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
);
|
|
}
|
|
|
|
// issue #1336 "take_escaped hangs if normal parser accepts empty"
|
|
#[test]
|
|
#[cfg_attr(debug_assertions, should_panic)]
|
|
fn complete_take_escaped_hang_2() {
|
|
// issue #1336 "take_escaped hangs if normal parser accepts empty"
|
|
fn escaped_string<'i>(input: &mut &'i str) -> TestResult<&'i str, &'i str> {
|
|
use crate::ascii::alpha0;
|
|
use crate::token::one_of;
|
|
take_escaped(alpha0, '\\', one_of(['n'])).parse_next(input)
|
|
}
|
|
|
|
let input = "a7";
|
|
assert_parse!(
|
|
escaped_string.parse_peek(input),
|
|
str![[r#"
|
|
Err(
|
|
Cut(
|
|
InputError {
|
|
input: "7",
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[cfg_attr(debug_assertions, should_panic)]
|
|
fn complete_take_escaped_hang_1118() {
|
|
// issue ##1118 take_escaped does not work with empty string
|
|
fn unquote<'i>(input: &mut &'i str) -> TestResult<&'i str, &'i str> {
|
|
use crate::combinator::delimited;
|
|
use crate::combinator::opt;
|
|
use crate::token::one_of;
|
|
|
|
delimited(
|
|
'"',
|
|
take_escaped(
|
|
opt(none_of(['\\', '"'])),
|
|
'\\',
|
|
one_of(['\\', '"', 'r', 'n', 't']),
|
|
),
|
|
'"',
|
|
)
|
|
.parse_next(input)
|
|
}
|
|
|
|
let input = r#""""#;
|
|
assert_parse!(
|
|
unquote.parse_peek(input),
|
|
str![[r#"
|
|
Err(
|
|
Cut(
|
|
InputError {
|
|
input: "/"",
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
);
|
|
}
|
|
|
|
#[cfg(feature = "alloc")]
|
|
#[allow(unused_variables)]
|
|
#[test]
|
|
fn complete_escaping() {
|
|
use crate::ascii::{alpha1 as alpha, digit1 as digit};
|
|
use crate::token::one_of;
|
|
|
|
fn esc<'i>(i: &mut &'i [u8]) -> TestResult<&'i [u8], &'i [u8]> {
|
|
take_escaped(alpha, '\\', one_of(['\"', 'n', '\\'])).parse_next(i)
|
|
}
|
|
assert_parse!(
|
|
esc.parse_peek(&b"abcd;"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
[
|
|
97,
|
|
98,
|
|
99,
|
|
100,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek(&b"ab\\\"cd;"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
[
|
|
97,
|
|
98,
|
|
92,
|
|
34,
|
|
99,
|
|
100,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek(&b"\\\"abcd;"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
[
|
|
92,
|
|
34,
|
|
97,
|
|
98,
|
|
99,
|
|
100,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek(&b"\\n;"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
[
|
|
92,
|
|
110,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek(&b"ab\\\"12"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
49,
|
|
50,
|
|
],
|
|
[
|
|
97,
|
|
98,
|
|
92,
|
|
34,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek(&b"AB\\"[..]),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek(&b"AB\\A"[..]),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
65,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
fn esc2<'i>(i: &mut &'i [u8]) -> TestResult<&'i [u8], &'i [u8]> {
|
|
take_escaped(digit, '\\', one_of(['\"', 'n', '\\'])).parse_next(i)
|
|
}
|
|
assert_parse!(
|
|
esc2.parse_peek(&b"12\\nnn34"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
110,
|
|
110,
|
|
51,
|
|
52,
|
|
],
|
|
[
|
|
49,
|
|
50,
|
|
92,
|
|
110,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[cfg(feature = "alloc")]
|
|
#[test]
|
|
fn complete_escaping_str() {
|
|
use crate::ascii::{alpha1 as alpha, digit1 as digit};
|
|
use crate::token::one_of;
|
|
|
|
fn esc<'i>(i: &mut &'i str) -> TestResult<&'i str, &'i str> {
|
|
take_escaped(alpha, '\\', one_of(['\"', 'n', '\\'])).parse_next(i)
|
|
}
|
|
assert_parse!(
|
|
esc.parse_peek("abcd;"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
";",
|
|
"abcd",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek("ab\\\"cd;"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
";",
|
|
"ab\\\"cd",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek("\\\"abcd;"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
";",
|
|
"\\\"abcd",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek("\\n;"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
";",
|
|
"\\n",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek("ab\\\"12"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"12",
|
|
"ab\\\"",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek("AB\\"),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: "",
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek("AB\\A"),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: "A",
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
fn esc2<'i>(i: &mut &'i str) -> TestResult<&'i str, &'i str> {
|
|
take_escaped(digit, '\\', one_of(['\"', 'n', '\\'])).parse_next(i)
|
|
}
|
|
assert_parse!(
|
|
esc2.parse_peek("12\\nnn34"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"nn34",
|
|
"12\\n",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
fn esc3<'i>(i: &mut &'i str) -> TestResult<&'i str, &'i str> {
|
|
take_escaped(alpha, '\u{241b}', one_of(['\"', 'n'])).parse_next(i)
|
|
}
|
|
assert_parse!(
|
|
esc3.parse_peek("ab␛ncd;"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
";",
|
|
"ab␛ncd",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_take_escaped_error() {
|
|
fn esc<'i>(i: &mut &'i str) -> TestResult<&'i str, &'i str> {
|
|
use crate::ascii::digit1;
|
|
take_escaped(digit1, '\\', one_of(['\"', 'n', '\\'])).parse_next(i)
|
|
}
|
|
|
|
assert_parse!(
|
|
esc.parse_peek("abcd"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"abcd",
|
|
"",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[cfg(feature = "alloc")]
|
|
#[test]
|
|
fn complete_escape_transform() {
|
|
use crate::ascii::alpha1 as alpha;
|
|
|
|
#[cfg(feature = "alloc")]
|
|
fn to_s(i: Vec<u8>) -> String {
|
|
String::from_utf8_lossy(&i).into_owned()
|
|
}
|
|
|
|
fn esc<'i>(i: &mut &'i [u8]) -> TestResult<&'i [u8], String> {
|
|
escaped(alpha, '\\', alt((b'\\', b'"', "n".value(b'\n'))))
|
|
.map(to_s)
|
|
.parse_next(i)
|
|
}
|
|
|
|
assert_parse!(
|
|
esc.parse_peek(&b"abcd;"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
"abcd",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek(&b"ab\\\"cd;"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
"ab\"cd",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek(&b"\\\"abcd;"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
"\"abcd",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek(&b"\\n;"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
"\n",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek(&b"ab\\\"12"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
49,
|
|
50,
|
|
],
|
|
"ab\"",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek(&b"AB\\"[..]),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek(&b"AB\\A"[..]),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
65,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
fn esc2<'i>(i: &mut &'i [u8]) -> TestResult<&'i [u8], String> {
|
|
escaped(
|
|
alpha,
|
|
'&',
|
|
alt((
|
|
"egrave;".value("è".as_bytes()),
|
|
"agrave;".value("à".as_bytes()),
|
|
)),
|
|
)
|
|
.map(to_s)
|
|
.parse_next(i)
|
|
}
|
|
assert_parse!(
|
|
esc2.parse_peek(&b"abèDEF;"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
"abèDEF",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc2.parse_peek(&b"abèDàEF;"[..]),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[
|
|
59,
|
|
],
|
|
"abèDàEF",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[cfg(feature = "std")]
|
|
#[test]
|
|
fn complete_escape_transform_str() {
|
|
use crate::ascii::alpha1 as alpha;
|
|
|
|
fn esc<'i>(i: &mut &'i str) -> TestResult<&'i str, String> {
|
|
escaped(
|
|
alpha,
|
|
'\\',
|
|
alt((
|
|
'\\',
|
|
'"',
|
|
"n".value('\n'),
|
|
("x", hex_uint).map(|(_, hex)| char::from_u32(hex).unwrap()),
|
|
)),
|
|
)
|
|
.parse_next(i)
|
|
}
|
|
|
|
assert_parse!(
|
|
esc.parse_peek("abcd;"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
";",
|
|
"abcd",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek("ab\\\"cd;"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
";",
|
|
"ab\"cd",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek("\\\"abcd;"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
";",
|
|
"\"abcd",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek("\\n;"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
";",
|
|
"\n",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek("ab\\\"12"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"12",
|
|
"ab\"",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek("ab\\x20"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"",
|
|
"ab ",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek("AB\\"),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: "",
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek("AB\\A"),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: "A",
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
fn esc2<'i>(i: &mut &'i str) -> TestResult<&'i str, String> {
|
|
escaped(
|
|
alpha,
|
|
'&',
|
|
alt(("egrave;".value("è"), "agrave;".value("à"))),
|
|
)
|
|
.parse_next(i)
|
|
}
|
|
assert_parse!(
|
|
esc2.parse_peek("abèDEF;"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
";",
|
|
"abèDEF",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc2.parse_peek("abèDàEF;"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
";",
|
|
"abèDàEF",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
fn esc3<'i>(i: &mut &'i str) -> TestResult<&'i str, String> {
|
|
escaped(alpha, '␛', alt(("0".value("\0"), "n".value("\n")))).parse_next(i)
|
|
}
|
|
assert_parse!(
|
|
esc3.parse_peek("a␛0bc␛n"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"",
|
|
"a\0bc\n",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[cfg(feature = "std")]
|
|
#[test]
|
|
fn complete_escape_transform_cow() {
|
|
use crate::ascii::alpha1 as alpha;
|
|
|
|
fn esc<'i>(i: &mut &'i str) -> TestResult<&'i str, alloc::borrow::Cow<'i, str>> {
|
|
escaped(
|
|
alpha,
|
|
'\\',
|
|
alt((
|
|
'\\',
|
|
'"',
|
|
"n".value('\n'),
|
|
("x", hex_uint).map(|(_, hex)| char::from_u32(hex).unwrap()),
|
|
)),
|
|
)
|
|
.parse_next(i)
|
|
}
|
|
|
|
assert_parse!(
|
|
esc.parse_peek("abcd;"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
";",
|
|
"abcd",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek("ab\\\"cd;"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
";",
|
|
"ab\"cd",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek("\\\"abcd;"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
";",
|
|
"\"abcd",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek("\\n;"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
";",
|
|
"\n",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek("ab\\\"12"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"12",
|
|
"ab\"",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek("ab\\x20"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"",
|
|
"ab ",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek("AB\\"),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: "",
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc.parse_peek("AB\\A"),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: "A",
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
fn esc2<'i>(i: &mut &'i str) -> TestResult<&'i str, alloc::borrow::Cow<'i, str>> {
|
|
escaped(
|
|
alpha,
|
|
'&',
|
|
alt(("egrave;".value("è"), "agrave;".value("à"))),
|
|
)
|
|
.parse_next(i)
|
|
}
|
|
assert_parse!(
|
|
esc2.parse_peek("abèDEF;"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
";",
|
|
"abèDEF",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
esc2.parse_peek("abèDàEF;"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
";",
|
|
"abèDàEF",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
fn esc3<'i>(i: &mut &'i str) -> TestResult<&'i str, String> {
|
|
escaped(alpha, '␛', alt(("0".value("\0"), "n".value("\n")))).parse_next(i)
|
|
}
|
|
assert_parse!(
|
|
esc3.parse_peek("a␛0bc␛n"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"",
|
|
"a\0bc\n",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[cfg(feature = "alloc")]
|
|
fn test_escaped_error() {
|
|
fn esc_trans<'i>(i: &mut &'i str) -> TestResult<&'i str, String> {
|
|
use crate::ascii::digit1;
|
|
escaped(digit1, '\\', "n").parse_next(i)
|
|
}
|
|
|
|
assert_parse!(
|
|
esc_trans.parse_peek("abcd"),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
"abcd",
|
|
"",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[cfg(feature = "alloc")]
|
|
fn try_fesc() {
|
|
const FEND: u8 = 0xC0;
|
|
const FESC: u8 = 0xDB;
|
|
const TFEND: u8 = 0xDC;
|
|
const TFESC: u8 = 0xDD;
|
|
|
|
fn unescape<'i>(input: &mut &'i [u8]) -> TestResult<&'i [u8], Vec<u8>> {
|
|
escaped(
|
|
take_till(1.., [FESC].as_slice()),
|
|
FESC,
|
|
alt((
|
|
(&[TFEND][..]).value(&[FEND][..]),
|
|
(&[TFESC][..]).value(&[FESC][..]),
|
|
)),
|
|
)
|
|
.parse_next(input)
|
|
}
|
|
|
|
// fesc
|
|
let input = &[0x61, 0x62, FESC, TFEND, 0x63, 0x64, 0x65][..];
|
|
assert_parse!(
|
|
unescape.parse_peek(input),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[],
|
|
[
|
|
97,
|
|
98,
|
|
192,
|
|
99,
|
|
100,
|
|
101,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
);
|
|
|
|
// fesczerozero
|
|
let input = &[0x61, FESC, 0x00, TFEND, 0x63, 0x64][..];
|
|
assert_parse!(
|
|
unescape.parse_peek(input),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: [
|
|
0,
|
|
220,
|
|
99,
|
|
100,
|
|
],
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
);
|
|
|
|
// noesc
|
|
let input = &[0x61, 0x62, 0x63][..];
|
|
assert_parse!(
|
|
unescape.parse_peek(input),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
[],
|
|
[
|
|
97,
|
|
98,
|
|
99,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
);
|
|
}
|
|
}
|
|
|
|
mod partial {
|
|
use super::*;
|
|
|
|
use crate::error::InputError;
|
|
use crate::prelude::*;
|
|
use crate::Partial;
|
|
|
|
#[test]
|
|
fn character() {
|
|
let a: &[u8] = b"abcd";
|
|
let b: &[u8] = b"1234";
|
|
let c: &[u8] = b"a123";
|
|
let d: &[u8] = "azé12".as_bytes();
|
|
let e: &[u8] = b" ";
|
|
let f: &[u8] = b" ;";
|
|
//assert_parse!(alpha1::<_, Error<_>>(a), Err(ErrMode::Incomplete(Needed::new(1))));
|
|
assert_parse!(
|
|
alpha1.parse_peek(Partial::new(a)),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Size(
|
|
1,
|
|
),
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
alpha1.parse_peek(Partial::new(b)),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: [
|
|
49,
|
|
50,
|
|
51,
|
|
52,
|
|
],
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
alpha1.parse_peek(Partial::new(c)),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: [
|
|
49,
|
|
50,
|
|
51,
|
|
],
|
|
partial: true,
|
|
},
|
|
[
|
|
97,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
alpha1.parse_peek(Partial::new(d)),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: [
|
|
195,
|
|
169,
|
|
49,
|
|
50,
|
|
],
|
|
partial: true,
|
|
},
|
|
[
|
|
97,
|
|
122,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
digit1.parse_peek(Partial::new(a)),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: [
|
|
97,
|
|
98,
|
|
99,
|
|
100,
|
|
],
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
digit1.parse_peek(Partial::new(b)),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Size(
|
|
1,
|
|
),
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
digit1.parse_peek(Partial::new(c)),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: [
|
|
97,
|
|
49,
|
|
50,
|
|
51,
|
|
],
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
digit1.parse_peek(Partial::new(d)),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: [
|
|
97,
|
|
122,
|
|
195,
|
|
169,
|
|
49,
|
|
50,
|
|
],
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(Partial::new(a)),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Size(
|
|
1,
|
|
),
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(Partial::new(b)),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Size(
|
|
1,
|
|
),
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(Partial::new(c)),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Size(
|
|
1,
|
|
),
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(Partial::new(d)),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: [
|
|
122,
|
|
195,
|
|
169,
|
|
49,
|
|
50,
|
|
],
|
|
partial: true,
|
|
},
|
|
[
|
|
97,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(Partial::new(e)),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: [
|
|
32,
|
|
],
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
oct_digit1.parse_peek(Partial::new(a)),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: [
|
|
97,
|
|
98,
|
|
99,
|
|
100,
|
|
],
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
oct_digit1.parse_peek(Partial::new(b)),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Size(
|
|
1,
|
|
),
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
oct_digit1.parse_peek(Partial::new(c)),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: [
|
|
97,
|
|
49,
|
|
50,
|
|
51,
|
|
],
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
oct_digit1.parse_peek(Partial::new(d)),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: [
|
|
97,
|
|
122,
|
|
195,
|
|
169,
|
|
49,
|
|
50,
|
|
],
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
alphanumeric1.parse_peek(Partial::new(a)),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Size(
|
|
1,
|
|
),
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
//assert_parse!(fix_error!(b,(), alphanumeric1), str![]);
|
|
assert_parse!(
|
|
alphanumeric1.parse_peek(Partial::new(c)),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Size(
|
|
1,
|
|
),
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
alphanumeric1.parse_peek(Partial::new(d)),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: [
|
|
195,
|
|
169,
|
|
49,
|
|
50,
|
|
],
|
|
partial: true,
|
|
},
|
|
[
|
|
97,
|
|
122,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
space1.parse_peek(Partial::new(e)),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Size(
|
|
1,
|
|
),
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
space1.parse_peek(Partial::new(f)),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: [
|
|
59,
|
|
],
|
|
partial: true,
|
|
},
|
|
[
|
|
32,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[cfg(feature = "alloc")]
|
|
#[test]
|
|
fn character_s() {
|
|
let a = "abcd";
|
|
let b = "1234";
|
|
let c = "a123";
|
|
let d = "azé12";
|
|
let e = " ";
|
|
assert_parse!(
|
|
alpha1.parse_peek(Partial::new(a)),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Size(
|
|
1,
|
|
),
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
alpha1.parse_peek(Partial::new(b)),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: "1234",
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
alpha1.parse_peek(Partial::new(c)),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: "123",
|
|
partial: true,
|
|
},
|
|
"a",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
alpha1.parse_peek(Partial::new(d)),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: "é12",
|
|
partial: true,
|
|
},
|
|
"az",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
digit1.parse_peek(Partial::new(a)),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: "abcd",
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
digit1.parse_peek(Partial::new(b)),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Size(
|
|
1,
|
|
),
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
digit1.parse_peek(Partial::new(c)),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: "a123",
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
digit1.parse_peek(Partial::new(d)),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: "azé12",
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(Partial::new(a)),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Size(
|
|
1,
|
|
),
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(Partial::new(b)),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Size(
|
|
1,
|
|
),
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(Partial::new(c)),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Size(
|
|
1,
|
|
),
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(Partial::new(d)),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: "zé12",
|
|
partial: true,
|
|
},
|
|
"a",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(Partial::new(e)),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: " ",
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
oct_digit1.parse_peek(Partial::new(a)),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: "abcd",
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
oct_digit1.parse_peek(Partial::new(b)),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Size(
|
|
1,
|
|
),
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
oct_digit1.parse_peek(Partial::new(c)),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: "a123",
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
oct_digit1.parse_peek(Partial::new(d)),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: "azé12",
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
alphanumeric1.parse_peek(Partial::new(a)),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Size(
|
|
1,
|
|
),
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
//assert_parse!(fix_error!(b,(), alphanumeric1), str![]);
|
|
assert_parse!(
|
|
alphanumeric1.parse_peek(Partial::new(c)),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Size(
|
|
1,
|
|
),
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
alphanumeric1.parse_peek(Partial::new(d)),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: "é12",
|
|
partial: true,
|
|
},
|
|
"az",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
space1.parse_peek(Partial::new(e)),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Size(
|
|
1,
|
|
),
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
use crate::stream::Offset;
|
|
#[test]
|
|
fn offset() {
|
|
let a = &b"abcd;"[..];
|
|
let b = &b"1234;"[..];
|
|
let c = &b"a123;"[..];
|
|
let d = &b" \t;"[..];
|
|
let e = &b" \t\r\n;"[..];
|
|
let f = &b"123abcDEF;"[..];
|
|
|
|
match alpha1::<_, InputError<_>>.parse_peek(Partial::new(a)) {
|
|
Ok((i, _)) => {
|
|
let i = i.into_inner();
|
|
assert_eq!(i.offset_from(&a) + i.len(), a.len());
|
|
}
|
|
_ => panic!("wrong return type in offset test for alpha"),
|
|
}
|
|
match digit1::<_, InputError<_>>.parse_peek(Partial::new(b)) {
|
|
Ok((i, _)) => {
|
|
let i = i.into_inner();
|
|
assert_eq!(i.offset_from(&b) + i.len(), b.len());
|
|
}
|
|
_ => panic!("wrong return type in offset test for digit"),
|
|
}
|
|
match alphanumeric1::<_, InputError<_>>.parse_peek(Partial::new(c)) {
|
|
Ok((i, _)) => {
|
|
let i = i.into_inner();
|
|
assert_eq!(i.offset_from(&c) + i.len(), c.len());
|
|
}
|
|
_ => panic!("wrong return type in offset test for alphanumeric"),
|
|
}
|
|
match space1::<_, InputError<_>>.parse_peek(Partial::new(d)) {
|
|
Ok((i, _)) => {
|
|
let i = i.into_inner();
|
|
assert_eq!(i.offset_from(&d) + i.len(), d.len());
|
|
}
|
|
_ => panic!("wrong return type in offset test for space"),
|
|
}
|
|
match multispace1::<_, InputError<_>>.parse_peek(Partial::new(e)) {
|
|
Ok((i, _)) => {
|
|
let i = i.into_inner();
|
|
assert_eq!(i.offset_from(&e) + i.len(), e.len());
|
|
}
|
|
_ => panic!("wrong return type in offset test for multispace"),
|
|
}
|
|
match hex_digit1::<_, InputError<_>>.parse_peek(Partial::new(f)) {
|
|
Ok((i, _)) => {
|
|
let i = i.into_inner();
|
|
assert_eq!(i.offset_from(&f) + i.len(), f.len());
|
|
}
|
|
_ => panic!("wrong return type in offset test for hex_digit"),
|
|
}
|
|
match oct_digit1::<_, InputError<_>>.parse_peek(Partial::new(f)) {
|
|
Ok((i, _)) => {
|
|
let i = i.into_inner();
|
|
assert_eq!(i.offset_from(&f) + i.len(), f.len());
|
|
}
|
|
_ => panic!("wrong return type in offset test for oct_digit"),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn is_till_line_ending_bytes() {
|
|
let a: &[u8] = b"ab12cd\nefgh";
|
|
assert_parse!(
|
|
till_line_ending.parse_peek(Partial::new(a)),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: [
|
|
10,
|
|
101,
|
|
102,
|
|
103,
|
|
104,
|
|
],
|
|
partial: true,
|
|
},
|
|
[
|
|
97,
|
|
98,
|
|
49,
|
|
50,
|
|
99,
|
|
100,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
let b: &[u8] = b"ab12cd\nefgh\nijkl";
|
|
assert_parse!(
|
|
till_line_ending.parse_peek(Partial::new(b)),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: [
|
|
10,
|
|
101,
|
|
102,
|
|
103,
|
|
104,
|
|
10,
|
|
105,
|
|
106,
|
|
107,
|
|
108,
|
|
],
|
|
partial: true,
|
|
},
|
|
[
|
|
97,
|
|
98,
|
|
49,
|
|
50,
|
|
99,
|
|
100,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
let c: &[u8] = b"ab12cd\r\nefgh\nijkl";
|
|
assert_parse!(
|
|
till_line_ending.parse_peek(Partial::new(c)),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: [
|
|
13,
|
|
10,
|
|
101,
|
|
102,
|
|
103,
|
|
104,
|
|
10,
|
|
105,
|
|
106,
|
|
107,
|
|
108,
|
|
],
|
|
partial: true,
|
|
},
|
|
[
|
|
97,
|
|
98,
|
|
49,
|
|
50,
|
|
99,
|
|
100,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
let d: &[u8] = b"ab12cd";
|
|
assert_parse!(
|
|
till_line_ending.parse_peek(Partial::new(d)),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Unknown,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn is_till_line_ending_str() {
|
|
let f = "βèƒôřè\rÂßÇáƒƭèř";
|
|
assert_parse!(
|
|
till_line_ending.parse_peek(Partial::new(f)),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: "\rÂßÇáƒƭèř",
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
let g2: &str = "ab12cd";
|
|
assert_parse!(
|
|
till_line_ending.parse_peek(Partial::new(g2)),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Unknown,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn hex_digit_test() {
|
|
let i = &b"0123456789abcdefABCDEF;"[..];
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(Partial::new(i)),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: [
|
|
59,
|
|
],
|
|
partial: true,
|
|
},
|
|
[
|
|
48,
|
|
49,
|
|
50,
|
|
51,
|
|
52,
|
|
53,
|
|
54,
|
|
55,
|
|
56,
|
|
57,
|
|
97,
|
|
98,
|
|
99,
|
|
100,
|
|
101,
|
|
102,
|
|
65,
|
|
66,
|
|
67,
|
|
68,
|
|
69,
|
|
70,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
let i = &b"g"[..];
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(Partial::new(i)),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: [
|
|
103,
|
|
],
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
let i = &b"G"[..];
|
|
assert_parse!(
|
|
hex_digit1.parse_peek(Partial::new(i)),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: [
|
|
71,
|
|
],
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
assert!(AsChar::is_hex_digit(b'0'));
|
|
assert!(AsChar::is_hex_digit(b'9'));
|
|
assert!(AsChar::is_hex_digit(b'a'));
|
|
assert!(AsChar::is_hex_digit(b'f'));
|
|
assert!(AsChar::is_hex_digit(b'A'));
|
|
assert!(AsChar::is_hex_digit(b'F'));
|
|
assert!(!AsChar::is_hex_digit(b'g'));
|
|
assert!(!AsChar::is_hex_digit(b'G'));
|
|
assert!(!AsChar::is_hex_digit(b'/'));
|
|
assert!(!AsChar::is_hex_digit(b':'));
|
|
assert!(!AsChar::is_hex_digit(b'@'));
|
|
assert!(!AsChar::is_hex_digit(b'\x60'));
|
|
}
|
|
|
|
#[test]
|
|
fn oct_digit_test() {
|
|
let i = &b"01234567;"[..];
|
|
assert_parse!(
|
|
oct_digit1.parse_peek(Partial::new(i)),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: [
|
|
59,
|
|
],
|
|
partial: true,
|
|
},
|
|
[
|
|
48,
|
|
49,
|
|
50,
|
|
51,
|
|
52,
|
|
53,
|
|
54,
|
|
55,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
let i = &b"8"[..];
|
|
assert_parse!(
|
|
oct_digit1.parse_peek(Partial::new(i)),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: [
|
|
56,
|
|
],
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
assert!(AsChar::is_oct_digit(b'0'));
|
|
assert!(AsChar::is_oct_digit(b'7'));
|
|
assert!(!AsChar::is_oct_digit(b'8'));
|
|
assert!(!AsChar::is_oct_digit(b'9'));
|
|
assert!(!AsChar::is_oct_digit(b'a'));
|
|
assert!(!AsChar::is_oct_digit(b'A'));
|
|
assert!(!AsChar::is_oct_digit(b'/'));
|
|
assert!(!AsChar::is_oct_digit(b':'));
|
|
assert!(!AsChar::is_oct_digit(b'@'));
|
|
assert!(!AsChar::is_oct_digit(b'\x60'));
|
|
}
|
|
|
|
#[test]
|
|
fn full_line_windows() {
|
|
#[allow(clippy::type_complexity)]
|
|
fn take_full_line<'i>(
|
|
i: &mut Partial<&'i [u8]>,
|
|
) -> TestResult<Partial<&'i [u8]>, (&'i [u8], &'i [u8])> {
|
|
(till_line_ending, line_ending).parse_next(i)
|
|
}
|
|
let input = b"abc\r\n";
|
|
let output = take_full_line.parse_peek(Partial::new(input));
|
|
assert_parse!(
|
|
output,
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: [],
|
|
partial: true,
|
|
},
|
|
(
|
|
[
|
|
97,
|
|
98,
|
|
99,
|
|
],
|
|
[
|
|
13,
|
|
10,
|
|
],
|
|
),
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn full_line_unix() {
|
|
#[allow(clippy::type_complexity)]
|
|
fn take_full_line<'i>(
|
|
i: &mut Partial<&'i [u8]>,
|
|
) -> TestResult<Partial<&'i [u8]>, (&'i [u8], &'i [u8])> {
|
|
(till_line_ending, line_ending).parse_next(i)
|
|
}
|
|
let input = b"abc\n";
|
|
let output = take_full_line.parse_peek(Partial::new(input));
|
|
assert_parse!(
|
|
output,
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: [],
|
|
partial: true,
|
|
},
|
|
(
|
|
[
|
|
97,
|
|
98,
|
|
99,
|
|
],
|
|
[
|
|
10,
|
|
],
|
|
),
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn check_windows_lineending() {
|
|
let input = b"\r\n";
|
|
let output = line_ending.parse_peek(Partial::new(&input[..]));
|
|
assert_parse!(
|
|
output,
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: [],
|
|
partial: true,
|
|
},
|
|
[
|
|
13,
|
|
10,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn check_unix_lineending() {
|
|
let input = b"\n";
|
|
let output = line_ending.parse_peek(Partial::new(&input[..]));
|
|
assert_parse!(
|
|
output,
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: [],
|
|
partial: true,
|
|
},
|
|
[
|
|
10,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn cr_lf() {
|
|
assert_parse!(
|
|
crlf.parse_peek(Partial::new(&b"\r\na"[..])),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: [
|
|
97,
|
|
],
|
|
partial: true,
|
|
},
|
|
[
|
|
13,
|
|
10,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
crlf.parse_peek(Partial::new(&b"\r"[..])),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Unknown,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
crlf.parse_peek(Partial::new(&b"\ra"[..])),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: [
|
|
13,
|
|
97,
|
|
],
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
assert_parse!(
|
|
crlf.parse_peek(Partial::new("\r\na")),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: "a",
|
|
partial: true,
|
|
},
|
|
"\r\n",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
crlf.parse_peek(Partial::new("\r")),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Unknown,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
crlf.parse_peek(Partial::new("\ra")),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: "\ra",
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn end_of_line() {
|
|
assert_parse!(
|
|
line_ending.parse_peek(Partial::new(&b"\na"[..])),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: [
|
|
97,
|
|
],
|
|
partial: true,
|
|
},
|
|
[
|
|
10,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
line_ending.parse_peek(Partial::new(&b"\r\na"[..])),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: [
|
|
97,
|
|
],
|
|
partial: true,
|
|
},
|
|
[
|
|
13,
|
|
10,
|
|
],
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
line_ending.parse_peek(Partial::new(&b"\r"[..])),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Unknown,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
line_ending.parse_peek(Partial::new(&b"\ra"[..])),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: [
|
|
13,
|
|
97,
|
|
],
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
|
|
assert_parse!(
|
|
line_ending.parse_peek(Partial::new("\na")),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: "a",
|
|
partial: true,
|
|
},
|
|
"\n",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
line_ending.parse_peek(Partial::new("\r\na")),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: "a",
|
|
partial: true,
|
|
},
|
|
"\r\n",
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
line_ending.parse_peek(Partial::new("\r")),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Unknown,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
line_ending.parse_peek(Partial::new("\ra")),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: "\ra",
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn hex_uint_tests() {
|
|
fn hex_u32<'i>(input: &mut Partial<&'i [u8]>) -> TestResult<Partial<&'i [u8]>, u32> {
|
|
hex_uint.parse_next(input)
|
|
}
|
|
|
|
assert_parse!(
|
|
hex_u32.parse_peek(Partial::new(&b";"[..])),
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: [
|
|
59,
|
|
],
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_u32.parse_peek(Partial::new(&b"ff;"[..])),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: [
|
|
59,
|
|
],
|
|
partial: true,
|
|
},
|
|
255,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_u32.parse_peek(Partial::new(&b"1be2;"[..])),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: [
|
|
59,
|
|
],
|
|
partial: true,
|
|
},
|
|
7138,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_u32.parse_peek(Partial::new(&b"c5a31be2;"[..])),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: [
|
|
59,
|
|
],
|
|
partial: true,
|
|
},
|
|
3315801058,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_u32.parse_peek(Partial::new(&b"C5A31be2;"[..])),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: [
|
|
59,
|
|
],
|
|
partial: true,
|
|
},
|
|
3315801058,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_u32.parse_peek(Partial::new(&b"00c5a31be2;"[..])), // overflow
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: [
|
|
48,
|
|
48,
|
|
99,
|
|
53,
|
|
97,
|
|
51,
|
|
49,
|
|
98,
|
|
101,
|
|
50,
|
|
59,
|
|
],
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_u32.parse_peek(Partial::new(&b"c5a31be201;"[..])), // overflow
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: [
|
|
99,
|
|
53,
|
|
97,
|
|
51,
|
|
49,
|
|
98,
|
|
101,
|
|
50,
|
|
48,
|
|
49,
|
|
59,
|
|
],
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_u32.parse_peek(Partial::new(&b"ffffffff;"[..])),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: [
|
|
59,
|
|
],
|
|
partial: true,
|
|
},
|
|
4294967295,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_u32.parse_peek(Partial::new(&b"ffffffffffffffff;"[..])), // overflow
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: [
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
59,
|
|
],
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_u32.parse_peek(Partial::new(&b"ffffffffffffffff"[..])), // overflow
|
|
str![[r#"
|
|
Err(
|
|
Backtrack(
|
|
InputError {
|
|
input: Partial {
|
|
input: [
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
102,
|
|
],
|
|
partial: true,
|
|
},
|
|
},
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_u32.parse_peek(Partial::new(&b"0x1be2;"[..])),
|
|
str![[r#"
|
|
Ok(
|
|
(
|
|
Partial {
|
|
input: [
|
|
120,
|
|
49,
|
|
98,
|
|
101,
|
|
50,
|
|
59,
|
|
],
|
|
partial: true,
|
|
},
|
|
0,
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
assert_parse!(
|
|
hex_u32.parse_peek(Partial::new(&b"12af"[..])),
|
|
str![[r#"
|
|
Err(
|
|
Incomplete(
|
|
Size(
|
|
1,
|
|
),
|
|
),
|
|
)
|
|
|
|
"#]]
|
|
.raw()
|
|
);
|
|
}
|
|
}
|