1use std::cell::RefCell;
2#[allow(unused_imports)]
3use std::ops::DerefMut;
4
5use winnow::combinator::cut_err;
6use winnow::combinator::delimited;
7use winnow::combinator::peek;
8use winnow::token::take;
9
10// https://github.com/rust-lang/rust/issues/41358
11use crate::parser::key::key;
12use crate::parser::prelude::*;
13use crate::parser::state::ParseState;
14use crate::parser::trivia::line_trailing;
15
16// std-table-open = %x5B ws ; [ Left square bracket
17pub(crate) const STD_TABLE_OPEN: u8 = b'[';
18// std-table-close = ws %x5D ; ] Right square bracket
19const STD_TABLE_CLOSE: u8 = b']';
20// array-table-open = %x5B.5B ws ; [[ Double left square bracket
21const ARRAY_TABLE_OPEN: &[u8] = b"[[";
22// array-table-close = ws %x5D.5D ; ]] Double right quare bracket
23const ARRAY_TABLE_CLOSE: &[u8] = b"]]";
24
25// ;; Standard Table
26
27// std-table = std-table-open key *( table-key-sep key) std-table-close
28pub(crate) fn std_table<'s, 'i>(
29 state: &'s RefCell<ParseState>,
30) -> impl Parser<Input<'i>, (), ContextError> + 's {
31 move |i: &mut Input<'i>| {
32 (
33 delimited(
34 STD_TABLE_OPEN,
35 cut_err(key),
36 cut_err(STD_TABLE_CLOSE)
37 .context(StrContext::Expected(StrContextValue::CharLiteral('.')))
38 .context(StrContext::Expected(StrContextValue::StringLiteral("]"))),
39 )
40 .with_span(),
41 cut_err(line_trailing)
42 .context(StrContext::Expected(StrContextValue::CharLiteral('\n')))
43 .context(StrContext::Expected(StrContextValue::CharLiteral('#'))),
44 )
45 .try_map(|((h, span), t)| state.borrow_mut().deref_mut().on_std_header(h, t, span))
46 .parse_next(input:i)
47 }
48}
49
50// ;; Array Table
51
52// array-table = array-table-open key *( table-key-sep key) array-table-close
53pub(crate) fn array_table<'s, 'i>(
54 state: &'s RefCell<ParseState>,
55) -> impl Parser<Input<'i>, (), ContextError> + 's {
56 move |i: &mut Input<'i>| {
57 (
58 delimited(
59 ARRAY_TABLE_OPEN,
60 cut_err(key),
61 cut_err(ARRAY_TABLE_CLOSE)
62 .context(StrContext::Expected(StrContextValue::CharLiteral('.')))
63 .context(StrContext::Expected(StrContextValue::StringLiteral("]]"))),
64 )
65 .with_span(),
66 cut_err(line_trailing)
67 .context(StrContext::Expected(StrContextValue::CharLiteral('\n')))
68 .context(StrContext::Expected(StrContextValue::CharLiteral('#'))),
69 )
70 .try_map(|((h, span), t)| state.borrow_mut().deref_mut().on_array_header(h, t, span))
71 .parse_next(input:i)
72 }
73}
74
75// ;; Table
76
77// table = std-table / array-table
78pub(crate) fn table<'s, 'i>(
79 state: &'s RefCell<ParseState>,
80) -> impl Parser<Input<'i>, (), ContextError> + 's {
81 move |i: &mut Input<'i>| {
82 dispatch!(peek::<_, &[u8],_,_>(take(2usize));
83 b"[[" => array_table(state),
84 _ => std_table(state),
85 )
86 .context(StrContext::Label("table header"))
87 .parse_next(input:i)
88 }
89}
90