css_parse/syntax/
function.rs1use crate::{Cursor, CursorSink, Parse, Parser, Peek, Result as ParserResult, Span, ToCursors, ToSpan, token_macros};
2use std::marker::PhantomData;
3
4#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
47#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
48pub struct Function<FT, T>
49where
50 FT: Into<token_macros::Function>,
51{
52 pub name: token_macros::Function,
53 pub parameters: T,
54 pub close: Option<token_macros::RightParen>,
55 #[cfg_attr(feature = "serde", serde(skip))]
56 _phantom: PhantomData<FT>,
57}
58
59impl<'a, FT, T> Peek<'a> for Function<FT, T>
60where
61 FT: Peek<'a> + Into<token_macros::Function>,
62{
63 fn peek(p: &Parser<'a>, c: Cursor) -> bool {
64 <FT>::peek(p, c)
65 }
66}
67
68impl<'a, FT, T> Parse<'a> for Function<FT, T>
69where
70 FT: Parse<'a> + Into<token_macros::Function>,
71 T: Parse<'a>,
72{
73 fn parse(p: &mut Parser<'a>) -> ParserResult<Self> {
74 let name = p.parse::<FT>()?.into();
75 let parameters = p.parse::<T>()?;
76 let close = p.parse_if_peek::<token_macros::RightParen>()?;
77 Ok(Self { name, parameters, close, _phantom: PhantomData })
78 }
79}
80
81impl<FT, T> ToCursors for Function<FT, T>
82where
83 FT: Into<token_macros::Function>,
84 T: ToCursors,
85{
86 fn to_cursors(&self, s: &mut impl CursorSink) {
87 s.append(self.name.into());
88 ToCursors::to_cursors(&self.parameters, s);
89 ToCursors::to_cursors(&self.close, s);
90 }
91}
92
93impl<FT, T> ToSpan for Function<FT, T>
94where
95 FT: Into<token_macros::Function>,
96 T: ToSpan,
97{
98 fn to_span(&self) -> Span {
99 self.name.to_span() + self.parameters.to_span() + self.close.to_span()
100 }
101}
102
103#[cfg(test)]
104mod tests {
105 use super::*;
106 use crate::{T, test_helpers::*};
107
108 type FunctionBlock<'a> = Function<T![Function], T![Ident]>;
109
110 #[test]
111 fn size_test() {
112 assert_eq!(std::mem::size_of::<FunctionBlock>(), 40);
113 }
114
115 #[test]
116 fn test_writes() {
117 assert_parse!(FunctionBlock, "foo(bar)");
118 }
119}