pub fn is_a<'a, I, F>(predicate: F) -> Parser<'a, I, I>
Expand description
Success when predicate returns true on current input symbol.
Examples found in repository?
examples/json_char.rs (line 47)
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
fn string<'a>() -> Parser<'a, char, String> {
let special_char = sym('\\')
| sym('/')
| sym('"')
| sym('b').map(|_| '\x08')
| sym('f').map(|_| '\x0C')
| sym('n').map(|_| '\n')
| sym('r').map(|_| '\r')
| sym('t').map(|_| '\t');
let escape_sequence = sym('\\') * special_char;
let char_string = (none_of("\\\"") | escape_sequence)
.repeat(1..)
.map(String::from_iter);
let utf16_char = tag("\\u")
* is_a(|c: char| c.is_digit(16))
.repeat(4)
.map(String::from_iter)
.convert(|digits| u16::from_str_radix(&digits, 16));
let utf16_string = utf16_char.repeat(1..).map(|chars| {
decode_utf16(chars)
.map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
.collect::<String>()
});
let string = sym('"') * (char_string | utf16_string).repeat(0..) - sym('"');
string.map(|strings| strings.concat())
}
More examples
examples/json.rs (line 47)
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
fn string<'a>() -> Parser<'a, u8, String> {
let special_char = sym(b'\\')
| sym(b'/')
| sym(b'"')
| sym(b'b').map(|_| b'\x08')
| sym(b'f').map(|_| b'\x0C')
| sym(b'n').map(|_| b'\n')
| sym(b'r').map(|_| b'\r')
| sym(b't').map(|_| b'\t');
let escape_sequence = sym(b'\\') * special_char;
let char_string = (none_of(b"\\\"") | escape_sequence)
.repeat(1..)
.convert(String::from_utf8);
let utf16_char = seq(b"\\u")
* is_a(hex_digit)
.repeat(4)
.convert(String::from_utf8)
.convert(|digits| u16::from_str_radix(&digits, 16));
let utf16_string = utf16_char.repeat(1..).map(|chars| {
decode_utf16(chars)
.map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
.collect::<String>()
});
let string = sym(b'"') * (char_string | utf16_string).repeat(0..) - sym(b'"');
string.map(|strings| strings.concat())
}
examples/json_file.rs (line 49)
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
fn string<'a>() -> Parser<'a, u8, String> {
let special_char = sym(b'\\')
| sym(b'/')
| sym(b'"')
| sym(b'b').map(|_| b'\x08')
| sym(b'f').map(|_| b'\x0C')
| sym(b'n').map(|_| b'\n')
| sym(b'r').map(|_| b'\r')
| sym(b't').map(|_| b'\t');
let escape_sequence = sym(b'\\') * special_char;
let char_string = (none_of(b"\\\"") | escape_sequence)
.repeat(1..)
.convert(String::from_utf8);
let utf16_char = seq(b"\\u")
* is_a(hex_digit)
.repeat(4)
.convert(String::from_utf8)
.convert(|digits| u16::from_str_radix(&digits, 16));
let utf16_string = utf16_char.repeat(1..).map(|chars| {
decode_utf16(chars)
.map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
.collect::<String>()
});
let string = sym(b'"') * (char_string | utf16_string).repeat(0..) - sym(b'"');
string.map(|strings| strings.concat())
}
examples/utf8_mixed.rs (line 30)
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
fn main() {
// A parser for MsgPack (but only messages encoding a string)
let testcases: [Vec<u8>; 6] = [
vec![0b10100100, 0b11110000, 0b10011111, 0b10100100, 0b10010100], // 🤔, max-size 31 format
vec![0xd9, 4, 0b11110000, 0b10011111, 0b10011000, 0b10101110], // 😮, max-size 255 format
vec![0xda, 0, 4, 0b11110000, 0b10011111, 0b10100100, 0b10101111], // 🤯, max-size 2^16-1 format
vec![
0xdb, 0, 0, 0, 4, 0b11110000, 0b10011111, 0b10010010, 0b10100101,
], // 💥, max-size 2^32-1 format
vec![0xc4, 4, 0b11110000, 0b10011111, 0b10011000, 0b10101110], // Valid MsgPack, but not a string (binary)
vec![0b10100100, 0b10010100, 0b10100100, 0b10011111, 0b11110000], // A MsgPack string, but invalid UTF-8
];
const MASK: u8 = 0b11100000; // size 31 format is denoted by 3 high bits == 101
const SIZE_31: u8 = 0b10100000;
fn rest_as_str<'a>() -> utf8::Parser<'a, &'a str> {
utf8::any().repeat(0..).collect()
}
// Demo parser does not verify that the claimed length matches the actual length (but checking so is simple with >>)
let parser = (sym(0xdb) * any().repeat(4) * rest_as_str()) // 2^32-1 format
| (sym(0xda) * any().repeat(2) * rest_as_str()) // 2^16-1 format
| (sym(0xd9) * any() * rest_as_str()) // 255 format
| (is_a(|x| x&MASK == SIZE_31) * rest_as_str()) // 31 format
- end();
for testcase in testcases.iter() {
println!("{:?}", parser.parse(testcase));
}
}