nom_input_aux/
lib.rs

1use std::ops::{
2	Range,
3	RangeFrom,
4	RangeFull,
5	RangeTo,
6};
7use std::str::FromStr;
8
9use nom::{
10	AsBytes,
11	Compare,
12	CompareResult,
13	Err,
14	FindSubstring,
15	FindToken,
16	InputIter,
17	InputLength,
18	InputTake,
19	InputTakeAtPosition,
20	Needed,
21	Offset,
22	ParseTo,
23	Slice,
24};
25use nom::error::{
26	ErrorKind,
27	ParseError,
28};
29
30/// Struct to carry auxiliary data along with the input.
31#[derive(Debug, Clone)]
32pub struct InputAux<Aux, I> {
33	/// Auxiliary data for the parsing logic.
34	pub aux: Aux,
35
36	/// Input to parse.
37	pub input: I
38}
39
40impl<Aux, I> InputAux<Aux, I> {
41	/// Create a new instance.
42	pub fn new(aux: Aux, buf: I) -> Self {
43		InputAux{aux, input: buf}
44	}
45}
46
47pub trait ContextAware<EE> {
48	// return None if successfully entered context, return Some(Ok()) if an error is to be signaled or Some(Err()) if a failure.
49	fn push_context(&mut self, context: &'static str) -> Option<Result<EE, EE>>;
50	fn pop_context<I, O, E: nom::error::FromExternalError<I, EE>>(&mut self, res: &nom::IResult<I, O, E>) -> Option<Result<EE, EE>>;
51}
52
53pub fn context<EE, Aux: Clone + ContextAware<EE>, I: Clone, E: nom::error::FromExternalError<InputAux<Aux, I>, EE> + nom::error::ContextError<InputAux<Aux, I>>, F, O>(
54	ctxt: &'static str,
55	mut f: F,
56) -> impl FnMut(InputAux<Aux, I>) -> nom::IResult<InputAux<Aux, I>, O, E>
57where
58	F: nom::Parser<InputAux<Aux, I>, O, E>,
59{
60	move |mut i: InputAux<Aux, I>| {
61		match i.aux.push_context(ctxt) {
62			None => (),
63			Some(Ok(e)) => return Err(Err::Error(E::from_external_error(i, ErrorKind::Not, e))),
64			Some(Err(f)) => return Err(Err::Failure(E::from_external_error(i, ErrorKind::Not, f))),
65		};
66		let res = f.parse(i.clone());
67		match i.aux.pop_context(&res) {
68			None => (),
69			Some(Ok(e)) => return Err(Err::Error(E::from_external_error(i, ErrorKind::Not, e))),
70			Some(Err(f)) => return Err(Err::Failure(E::from_external_error(i, ErrorKind::Not, f))),
71		};
72		match res {
73			Ok(o) => Ok(o),
74			Err(Err::Incomplete(i)) => Err(Err::Incomplete(i)),
75			Err(Err::Error(e)) => Err(Err::Error(E::add_context(i, ctxt, e))),
76			Err(Err::Failure(e)) => Err(Err::Failure(E::add_context(i, ctxt, e))),
77		}
78	}
79}
80
81impl <Aux: Copy, I> InputAux<Aux, I> {
82	/// Create a new instance with a copy of the auxiliary data.
83	pub fn wrap_with(&self, buf: I) -> Self {
84		Self::new(self.aux, buf)
85	}
86
87	/// Create new instances, each with a copy of the auxiliary data.
88	pub fn split_aux(&self, t1: I, t2: I) -> (Self, Self) {
89		(Self::new(self.aux, t1), Self::new(self.aux, t2))
90	}
91}
92
93impl <Aux: Default, I> From<I> for InputAux<Aux, I> {
94	fn from(i: I) -> Self { InputAux::new(Default::default(), i) }
95}
96
97impl <Aux, I: PartialEq> PartialEq for InputAux<Aux, I> {
98	fn eq(&self, rhs: &Self) -> bool {
99		self.input == rhs.input
100	}
101}
102
103impl <Aux, I: Eq> Eq for InputAux<Aux, I> { }
104
105impl <Aux: Copy, I: Copy> Copy for InputAux<Aux, I> { }
106
107impl <Aux, I> std::borrow::Borrow<I> for InputAux<Aux, &I> {
108	fn borrow(&self) -> &I {
109		self.input
110	}
111}
112
113impl<Aux, I: InputLength> InputLength for InputAux<Aux, I> {
114	#[inline]
115	fn input_len(&self) -> usize {
116		self.input.input_len()
117	}
118}
119
120
121impl<Aux, I: Offset> Offset for InputAux<Aux, I> {
122	fn offset(&self, second: &Self) -> usize {
123		self.input.offset(&second.input)
124	}
125}
126
127
128impl<Aux, I: AsBytes> AsBytes for InputAux<Aux, I> {
129	#[inline(always)]
130	fn as_bytes(&self) -> &[u8] {
131		self.input.as_bytes()
132	}
133}
134
135impl <Aux, I: InputIter> InputIter for InputAux<Aux, I> {
136	type Item = <I as InputIter>::Item;
137	type Iter = <I as InputIter>::Iter;
138	type IterElem = <I as InputIter>::IterElem;
139
140	fn iter_indices(&self) -> Self::Iter { self.input.iter_indices() }
141
142	fn iter_elements(&self) -> Self::IterElem { self.input.iter_elements() }
143
144	fn position<P: Fn(Self::Item) -> bool>(&self, p: P) -> Option<usize> {
145		self.input.position(p)
146	}
147
148	fn slice_index(&self, i: usize) -> Result<usize, Needed> {
149		self.input.slice_index(i)
150	}
151}
152
153impl <Aux: Copy, I: InputTake> InputTake for InputAux<Aux, I> {
154	fn take(&self, n: usize) -> Self {
155		InputAux::new(self.aux, self.input.take(n))
156	}
157
158	fn take_split(&self, n: usize) -> (Self, Self) {
159		let (t1, t2) = self.input.take_split(n);
160
161		(InputAux::new(self.aux, t1), InputAux::new(self.aux, t2))
162	}
163}
164
165
166impl <Aux: Copy, I: InputIter + InputTakeAtPosition> InputTakeAtPosition for InputAux<Aux, I> {
167	type Item = <I as InputTakeAtPosition>::Item;
168
169	fn split_at_position<P: Fn(Self::Item) -> bool, E: ParseError<Self>>(&self, pred: P) -> Result<(Self, Self), Err<E>> {
170		let r = self.input.split_at_position::<P, (I, ErrorKind)>(pred);
171		let r = r.map(|(p1, p2)| self.split_aux(p1, p2));
172		let r = r.map_err(|e| e.map(|i| E::from_error_kind(self.wrap_with(i.0), i.1)));
173		r
174	}
175
176	fn split_at_position1<P: Fn(Self::Item) -> bool, E: ParseError<Self>>(&self, pred: P, kind: ErrorKind) -> Result<(Self, Self), Err<E>> {
177		let r = self.input.split_at_position1::<P, (I, ErrorKind)>(pred, kind);
178		let r = r.map(|(p1, p2)| self.split_aux(p1, p2));
179		let r = r.map_err(|e| { let ee = e.map(|i| { let o: E = E::from_error_kind(self.wrap_with(i.0), i.1); o }); ee });
180		r
181	}
182
183	fn split_at_position_complete<P: Fn(Self::Item) -> bool, E: ParseError<Self>>(&self, pred: P) -> Result<(Self, Self), Err<E>> {
184		let r = self.input.split_at_position_complete::<P, (I, ErrorKind)>(pred);
185		let r = r.map(|(p1, p2)| self.split_aux(p1, p2));
186		let r = r.map_err(|e| { let ee = e.map(|i| { let o: E = E::from_error_kind(self.wrap_with(i.0), i.1); o }); ee });
187		r
188	}
189
190	fn split_at_position1_complete<P, E>(&self, pred: P, kind: ErrorKind) -> Result<(Self, Self), Err<E>>
191	where
192		P: Fn(Self::Item) -> bool,
193		E: ParseError<Self>,
194	{
195		let r = self.input.split_at_position1_complete::<P, (I, ErrorKind)>(pred, kind);
196		let r = r.map(|(p1, p2)| self.split_aux(p1, p2));
197		let r = r.map_err(|e| { let ee = e.map(|i| { let o: E = E::from_error_kind(self.wrap_with(i.0), i.1); o }); ee });
198		r
199	}
200}
201
202
203/* Blanket impl for Compare<> makes nom::number::complete::double() fail to compile
204impl <Aux, I: Compare<I>> Compare<I> for InputAux<Aux, I> {
205	fn compare(&self, v: I) -> CompareResult {
206		self.input.compare(v)
207	}
208
209	fn compare_no_case(&self, v: I) -> CompareResult {
210		self.input.compare_no_case(v)
211	}
212}
213
214*/
215impl <'a, Aux, I: Compare<&'a str>> Compare<&'a str> for InputAux<Aux, I> {
216	fn compare(&self, v: &'a str) -> CompareResult {
217		self.input.compare(v)
218	}
219
220	fn compare_no_case(&self, v: &'a str) -> CompareResult {
221		self.input.compare_no_case(v)
222	}
223}
224
225
226impl <'a, Aux, I: Compare<&'a [u8]>> Compare<&'a [u8]> for InputAux<Aux, I> {
227	fn compare(&self, v: &'a [u8]) -> CompareResult {
228		self.input.compare(v)
229	}
230
231	fn compare_no_case(&self, v: &'a [u8]) -> CompareResult {
232		self.input.compare_no_case(v)
233	}
234}
235
236
237impl<Aux, T, I: FindToken<T>> FindToken<T> for InputAux<Aux, I> {
238	fn find_token(&self, token: T) -> bool {
239		self.input.find_token(token)
240	}
241}
242
243
244impl<Aux, T, I: FindSubstring<T>> FindSubstring<T> for InputAux<Aux, I> {
245	fn find_substring(&self, substr: T) -> Option<usize> {
246		self.input.find_substring(substr)
247	}
248}
249
250
251impl<Aux, R: FromStr, I: ParseTo<R>> ParseTo<R> for InputAux<Aux, I> {
252	fn parse_to(&self) -> Option<R> {
253		self.input.parse_to()
254	}
255}
256
257
258macro_rules! aux_wrap {
259		( $ty:ty ) => {
260			impl <Aux: Copy, I: Slice<$ty>> Slice<$ty> for InputAux<Aux, I> {
261				fn slice(&self, r: $ty) -> Self {
262					self.wrap_with(self.input.slice(r))
263				}
264			}
265		}
266}
267
268aux_wrap! {Range<usize>}
269aux_wrap! {RangeTo<usize>}
270aux_wrap! {RangeFrom<usize>}
271aux_wrap! {RangeFull}
272
273impl<Aux, I: std::ops::Deref> std::ops::Deref for InputAux<Aux, I> {
274	type Target = <I as std::ops::Deref>::Target;
275
276	fn deref(&self) -> &<Self as std::ops::Deref>::Target {
277		self.input.deref()
278	}
279}
280
281#[cfg(test)]
282mod test {
283	#[cfg(feature = "alloc")]
284	use nom::{branch::alt, bytes::complete::tag_no_case, combinator::recognize, multi::many1};
285	use nom::{
286		bytes::complete::{is_a, is_not, tag, take, take_till, take_until},
287		error::{self, ErrorKind},
288		Err, IResult,
289		Needed,
290	};
291	use crate::InputAux;
292
293	#[test]
294	fn tagtr_succeed() {
295		const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "Hello World!" };
296		const TAG: &str = "Hello";
297		fn test(input: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
298			tag(TAG)(input)
299		}
300
301		match test(INPUT) {
302			Ok((extra, output)) => {
303				assert!(extra.input == " World!", "Parser `tag` consumed leftover input.");
304				assert!(
305					output.input == TAG,
306					"Parser `tag` doesn't return the tag it matched on success. \
307					 Expected `{}`, got `{}`.",
308					TAG,
309					output.input
310				);
311			}
312			other => panic!(
313				"Parser `tag` didn't succeed when it should have. \
314				 Got `{:?}`.",
315				other
316			),
317		};
318	}
319
320	#[test]
321	fn tagtr_incomplete() {
322		use nom::bytes::streaming::tag;
323
324		const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "Hello"	};
325		const TAG: &str = "Hello World!";
326
327		let res: IResult<_, _, error::Error<_>> = tag(TAG)(INPUT);
328		match res {
329			Err(Err::Incomplete(_)) => (),
330			other => {
331				panic!(
332					"Parser `tag` didn't require more input when it should have. \
333					 Got `{:?}`.",
334					other
335				);
336			}
337		};
338	}
339
340	#[test]
341	fn tagtr_error() {
342		const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "Hello World!"	};
343		const TAG: &str = "Random"; // TAG must be closer than INPUT.
344
345		let res: IResult<_, _, error::Error<_>> = tag(TAG)(INPUT);
346		match res {
347			Err(Err::Error(_)) => (),
348			other => {
349				panic!(
350					"Parser `tag` didn't fail when it should have. Got `{:?}`.`",
351					other
352				);
353			}
354		};
355	}
356
357	#[test]
358	fn take_s_succeed() {
359		const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇáƒƭèř"	};
360		const CONSUMED: &str = "βèƒôřèÂßÇ";
361		const LEFTOVER: &str = "áƒƭèř";
362
363		let res: IResult<_, _, error::Error<_>> = take(9_usize)(INPUT);
364		match res {
365			Ok((extra, output)) => {
366				assert!(
367					extra.input == LEFTOVER,
368					"Parser `take_s` consumed leftover input. Leftover `{}`.",
369					extra.input
370				);
371				assert!(
372					output.input == CONSUMED,
373					"Parser `take_s` doens't return the string it consumed on success. Expected `{}`, got `{}`.",
374					CONSUMED,
375					output.input
376				);
377			}
378			other => panic!(
379				"Parser `take_s` didn't succeed when it should have. \
380				 Got `{:?}`.",
381				other
382			),
383		};
384	}
385
386	#[test]
387	fn take_until_succeed() {
388		const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇ∂áƒƭèř"	};
389		const FIND: &str = "ÂßÇ∂";
390		const CONSUMED: &str = "βèƒôřè";
391		const LEFTOVER: &str = "ÂßÇ∂áƒƭèř";
392
393		let res: IResult<_, _, (_, ErrorKind)> = take_until(FIND)(INPUT);
394		match res {
395			Ok((extra, output)) => {
396				assert!(
397					extra.input == LEFTOVER,
398					"Parser `take_until`\
399					 consumed leftover input. Leftover `{}`.",
400					extra.input
401				);
402				assert!(
403					output.input == CONSUMED,
404					"Parser `take_until`\
405					 doens't return the string it consumed on success. Expected `{}`, got `{}`.",
406					CONSUMED,
407					output.input
408				);
409			}
410			other => panic!(
411				"Parser `take_until` didn't succeed when it should have. \
412				 Got `{:?}`.",
413				other
414			),
415		};
416	}
417
418	#[test]
419	fn take_s_incomplete() {
420		use nom::bytes::streaming::take;
421
422		const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇá"	};
423
424		let res: IResult<_, _, (_, ErrorKind)> = take(13_usize)(INPUT);
425		match res {
426			Err(Err::Incomplete(_)) => (),
427			other => panic!(
428				"Parser `take` didn't require more input when it should have. \
429				 Got `{:?}`.",
430				other
431			),
432		}
433	}
434
435	fn is_alphabetic(c: char) -> bool {
436		(c as u8 >= 0x41 && c as u8 <= 0x5A) || (c as u8 >= 0x61 && c as u8 <= 0x7A)
437	}
438
439	#[test]
440	fn take_while() {
441		use nom::bytes::streaming::take_while;
442
443		fn f(i: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
444			take_while(is_alphabetic)(i)
445		}
446		let a = "";
447		let b = "abcd";
448		let c = "abcd123";
449		let d = "123";
450
451		assert_eq!(f((&a[..]).into()), Err(Err::Incomplete(Needed::new(1))));
452		assert_eq!(f((&b[..]).into()), Err(Err::Incomplete(Needed::new(1))));
453		assert_eq!(f((&c[..]).into()), Ok(((&d[..]).into(), (&b[..]).into())));
454		assert_eq!(f((&d[..]).into()), Ok(((&d[..]).into(), (&a[..]).into())));
455	}
456
457	#[test]
458	fn take_while1() {
459		use nom::bytes::streaming::take_while1;
460
461		fn f(i: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
462			take_while1(is_alphabetic)(i)
463		}
464		let a = "";
465		let b = "abcd";
466		let c = "abcd123";
467		let d = "123";
468
469		assert_eq!(f((&a[..]).into()), Err(Err::Incomplete(Needed::new(1))));
470		assert_eq!(f((&b[..]).into()), Err(Err::Incomplete(Needed::new(1))));
471		assert_eq!(f((&c[..]).into()), Ok(((&"123"[..]).into(), (&b[..]).into())));
472		assert_eq!(
473			f((&d[..]).into()),
474			Err(Err::Error(nom::error_position!((&d[..]).into(), ErrorKind::TakeWhile1)))
475		);
476	}
477
478	#[test]
479	fn take_till_s_succeed() {
480		const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇáƒƭèř"	};
481		const CONSUMED: &str = "βèƒôřèÂßÇ";
482		const LEFTOVER: &str = "áƒƭèř";
483		fn till_s(c: char) -> bool {
484			c == 'á'
485		}
486		fn test(input: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
487			take_till(till_s)(input)
488		}
489		match test(INPUT) {
490			Ok((extra, output)) => {
491				assert!(
492					extra.input == LEFTOVER,
493					"Parser `take_till` consumed leftover input."
494				);
495				assert!(
496					output.input == CONSUMED,
497					"Parser `take_till` doesn't return the string it consumed on success. \
498					 Expected `{}`, got `{}`.",
499					CONSUMED,
500					output.input
501				);
502			}
503			other => panic!(
504				"Parser `take_till` didn't succeed when it should have. \
505				 Got `{:?}`.",
506				other
507			),
508		};
509	}
510
511	#[test]
512	fn take_while_succeed_none() {
513		use nom::bytes::complete::take_while;
514
515		const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇáƒƭèř"	};
516		const CONSUMED: &str = "";
517		const LEFTOVER: &str = "βèƒôřèÂßÇáƒƭèř";
518		fn while_s(c: char) -> bool {
519			c == '9'
520		}
521		fn test(input: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
522			take_while(while_s)(input)
523		}
524		match test(INPUT) {
525			Ok((extra, output)) => {
526				assert!(
527					extra.input == LEFTOVER,
528					"Parser `take_while` consumed leftover input."
529				);
530				assert!(
531					output.input == CONSUMED,
532					"Parser `take_while` doesn't return the string it consumed on success. \
533					 Expected `{}`, got `{}`.",
534					CONSUMED,
535					output.input
536				);
537			}
538			other => panic!(
539				"Parser `take_while` didn't succeed when it should have. \
540				 Got `{:?}`.",
541				other
542			),
543		};
544	}
545
546	#[test]
547	fn is_not_succeed() {
548		const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇáƒƭèř"	};
549		const AVOID: &str = "£úçƙ¥á";
550		const CONSUMED: &str = "βèƒôřèÂßÇ";
551		const LEFTOVER: &str = "áƒƭèř";
552		fn test(input: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
553			is_not(AVOID)(input)
554		}
555		match test(INPUT) {
556			Ok((extra, output)) => {
557				assert!(
558					extra.input == LEFTOVER,
559					"Parser `is_not` consumed leftover input. Leftover `{}`.",
560					extra.input
561				);
562				assert!(
563					output.input == CONSUMED,
564					"Parser `is_not` doens't return the string it consumed on success. Expected `{}`, got `{}`.",
565					CONSUMED,
566					output.input
567				);
568			}
569			other => panic!(
570				"Parser `is_not` didn't succeed when it should have. \
571				 Got `{:?}`.",
572				other
573			),
574		};
575	}
576
577	#[test]
578	fn take_while_succeed_some() {
579		use nom::bytes::complete::take_while;
580
581		const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇáƒƭèř"	};
582		const CONSUMED: &str = "βèƒôřèÂßÇ";
583		const LEFTOVER: &str = "áƒƭèř";
584		fn while_s(c: char) -> bool {
585			c == 'β'
586				|| c == 'è'
587				|| c == 'ƒ'
588				|| c == 'ô'
589				|| c == 'ř'
590				|| c == 'è'
591				|| c == 'Â'
592				|| c == 'ß'
593				|| c == 'Ç'
594		}
595		fn test(input: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
596			take_while(while_s)(input)
597		}
598		match test(INPUT) {
599			Ok((extra, output)) => {
600				assert!(
601					extra.input == LEFTOVER,
602					"Parser `take_while` consumed leftover input."
603				);
604				assert!(
605					output.input == CONSUMED,
606					"Parser `take_while` doesn't return the string it consumed on success. \
607					 Expected `{}`, got `{}`.",
608					CONSUMED,
609					output.input
610				);
611			}
612			other => panic!(
613				"Parser `take_while` didn't succeed when it should have. \
614				 Got `{:?}`.",
615				other
616			),
617		};
618	}
619
620	#[test]
621	fn is_not_fail() {
622		const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇáƒƭèř"	};
623		const AVOID: InputAux<(), &str> = InputAux { aux: (), input: "βúçƙ¥"	};
624		fn test(input: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
625			is_not(AVOID)(input)
626		}
627		match test(INPUT) {
628			Err(Err::Error(_)) => (),
629			other => panic!(
630				"Parser `is_not` didn't fail when it should have. Got `{:?}`.",
631				other
632			),
633		};
634	}
635
636	#[test]
637	fn take_while1_succeed() {
638		use nom::bytes::complete::take_while1;
639
640		const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇáƒƭèř"	};
641		const CONSUMED: &str = "βèƒôřèÂßÇ";
642		const LEFTOVER: &str = "áƒƭèř";
643		fn while1_s(c: char) -> bool {
644			c == 'β'
645				|| c == 'è'
646				|| c == 'ƒ'
647				|| c == 'ô'
648				|| c == 'ř'
649				|| c == 'è'
650				|| c == 'Â'
651				|| c == 'ß'
652				|| c == 'Ç'
653		}
654		fn test(input: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
655			take_while1(while1_s)(input)
656		}
657		match test(INPUT) {
658			Ok((extra, output)) => {
659				assert!(
660					extra.input == LEFTOVER,
661					"Parser `take_while1` consumed leftover input."
662				);
663				assert!(
664					output.input == CONSUMED,
665					"Parser `take_while1` doesn't return the string it consumed on success. \
666					 Expected `{}`, got `{}`.",
667					CONSUMED,
668					output.input
669				);
670			}
671			other => panic!(
672				"Parser `take_while1` didn't succeed when it should have. \
673				 Got `{:?}`.",
674				other
675			),
676		};
677	}
678
679	#[test]
680	fn take_until_incomplete() {
681		use nom::bytes::streaming::take_until;
682
683		const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřè"	};
684		const FIND: &str = "βèƒôřèÂßÇ";
685
686		let res: IResult<_, _, (_, ErrorKind)> = take_until(FIND)(INPUT);
687		match res {
688			Err(Err::Incomplete(_)) => (),
689			other => panic!(
690				"Parser `take_until` didn't require more input when it should have. \
691				 Got `{:?}`.",
692				other
693			),
694		};
695	}
696
697	#[test]
698	fn is_a_succeed() {
699		const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇáƒƭèř"	};
700		const MATCH: &str = "βèƒôřèÂßÇ";
701		const CONSUMED: &str = "βèƒôřèÂßÇ";
702		const LEFTOVER: &str = "áƒƭèř";
703		fn test(input: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
704			is_a(MATCH)(input)
705		}
706		match test(INPUT) {
707			Ok((extra, output)) => {
708				assert!(
709					extra.input == LEFTOVER,
710					"Parser `is_a` consumed leftover input. Leftover `{}`.",
711					extra.input
712				);
713				assert!(
714					output.input == CONSUMED,
715					"Parser `is_a` doens't return the string it consumed on success. Expected `{}`, got `{}`.",
716					CONSUMED,
717					output.input
718				);
719			}
720			other => panic!(
721				"Parser `is_a` didn't succeed when it should have. \
722				 Got `{:?}`.",
723				other
724			),
725		};
726	}
727
728	#[test]
729	fn take_while1_fail() {
730		use nom::bytes::complete::take_while1;
731
732		const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇáƒƭèř"	};
733		fn while1_s(c: char) -> bool {
734			c == '9'
735		}
736		fn test(input: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
737			take_while1(while1_s)(input)
738		}
739		match test(INPUT) {
740			Err(Err::Error(_)) => (),
741			other => panic!(
742				"Parser `take_while1` didn't fail when it should have. \
743				 Got `{:?}`.",
744				other
745			),
746		};
747	}
748
749	#[test]
750	fn is_a_fail() {
751		const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇáƒƭèř"	};
752		const MATCH: &str = "Ûñℓúçƙ¥";
753		fn test(input: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
754			is_a(MATCH)(input)
755		}
756		match test(INPUT) {
757			Err(Err::Error(_)) => (),
758			other => panic!(
759				"Parser `is_a` didn't fail when it should have. Got `{:?}`.",
760				other
761			),
762		};
763	}
764
765	#[test]
766	fn take_until_error() {
767		use nom::bytes::streaming::take_until;
768
769		const INPUT: InputAux<(), &str> = InputAux { aux: (), input: "βèƒôřèÂßÇáƒƭèř" };
770		const FIND: &str = "Ráñδô₥";
771
772		let res: IResult<_, _, (_, ErrorKind)> = take_until(FIND)(INPUT);
773		match res {
774			Err(Err::Incomplete(_)) => (),
775			other => panic!(
776				"Parser `take_until` didn't fail when it should have. \
777				 Got `{:?}`.",
778				other
779			),
780		};
781	}
782
783	#[test]
784	#[cfg(feature = "alloc")]
785	fn recognize_is_a() {
786		let a = "aabbab";
787		let b = "ababcd";
788
789		fn f(i: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
790			recognize(many1(alt((tag("a"), tag("b")))))(i)
791		}
792
793		assert_eq!(f((&a[..]).into()), Ok(((&a[6..]).into(), (&a[..]).into())));
794		assert_eq!(f((&b[..]).into()), Ok(((&b[4..]).into(), (&b[..4]).into())));
795	}
796
797	#[test]
798	fn utf8_indexing() {
799		fn dot(i: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
800			tag(".")(i)
801		}
802
803		let _ = dot("點".into());
804	}
805
806	#[cfg(feature = "alloc")]
807	#[test]
808	fn case_insensitive() {
809		fn test(i: InputAux<(), &str>) -> IResult<InputAux<(), &str>, InputAux<(), &str>> {
810			tag_no_case("ABcd")(i)
811		}
812		assert_eq!(test("aBCdefgh".into()), Ok(("efgh".into(), "aBCd".into())));
813		assert_eq!(test("abcdefgh".into()), Ok(("efgh".into(), "abcd".into())));
814		assert_eq!(test("ABCDefgh".into()), Ok(("efgh".into(), "ABCD".into())));
815	}
816
817	#[test]
818	fn recurse_limit() {
819		use nom::branch::alt;
820		use nom::bytes::complete::tag;
821		use nom::sequence::delimited;
822
823		const DEPTH: i32 = 8;
824		const INPUT: InputAux<i32, &str> = InputAux { aux: 0, input: "([([([([x])])])]) World!" };
825
826		fn test(depth: i32, mut input: InputAux<i32, &str>) -> nom::IResult<InputAux<i32, &str>, InputAux<i32, &str>> {
827			fn cp(mut i: InputAux<i32, &str>) -> nom::IResult<InputAux<i32, &str>, InputAux<i32, &str>> {
828				i.aux -= 1;
829				if i.aux < 0 {
830					tag("never match")(i)
831				} else {
832					delimited(tag("("), alt((tag("x"), cp, csp)), tag(")"))(i)
833				}
834			}
835			fn csp(mut i: InputAux<i32, &str>) -> nom::IResult<InputAux<i32, &str>, InputAux<i32, &str>> {
836				i.aux -= 1;
837				if i.aux < 0 {
838					tag("never match")(i)
839				} else {
840					delimited(tag("["), alt((tag("x"), cp, csp)), tag("]"))(i)
841				}
842			}
843			input.aux = depth;
844			alt((cp, csp))(input)
845		}
846
847		match test(DEPTH, INPUT) {
848			Ok((extra, output)) => {
849				assert!(extra.input == " World!", "Parser `tag` consumed leftover input.");
850				assert!(output.aux == 0, "Depth left over not what should be {} != 0.", output.aux);
851				assert!(
852					output.input == "x",
853					"Parser `tag` doesn't return the tag it matched on success. \
854					 Expected `{}`, got `{}`.",
855					"x",
856					output.input
857				);
858			}
859			other => panic!(
860				"Parser `tag` didn't succeed when it should have. \
861				 Got `{:?}`.",
862				other
863			),
864		};
865
866		match test(DEPTH - 1, INPUT) {
867			Err(Err::Error(_)) => (),
868			other => panic!(
869				"Parser didn't reach max depth when it should have. \
870				 Got `{:?}`.",
871				other
872			),
873		};
874	}
875
876	#[test]
877	fn double_parsing() {
878		assert!(1.0 < nom::number::complete::double::<_, (_, ErrorKind)>("1.2").map(|v| v.1).unwrap_or(0.0));
879		assert!(1.0 < nom::number::complete::double::<_, (_, ErrorKind)>("1.2".as_bytes()).map(|v| v.1).unwrap_or(0.0));
880		assert!(1.0 < nom::number::complete::double::<_, (_, ErrorKind)>(InputAux{aux: (), input: "1.2"}).map(|v| v.1).unwrap_or(0.0));
881	}
882}