Function pom::parser::is_a

source ·
pub fn is_a<'a, I, F>(predicate: F) -> Parser<'a, I, I>
where I: Clone + PartialEq + Display + Debug, F: Fn(I) -> bool + 'a,
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
Hide additional 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));
	}
}