1
2
3
4
5
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
use thiserror::Error;

use lang_util::{
    located::{Located, LocatedBuilder},
    FileId,
};

use crate::{last::LocatedIterator, parser, types::path::ParsedPath};

use super::{
    event::Event,
    expand::{ExpandEvent, ExpandOne},
    ProcessorState,
};

pub fn parse(input: &str) -> parser::Ast {
    parser::Parser::new(input).parse()
}

#[derive(Debug, PartialEq, Eq, Error)]
pub enum ProcessStrError {
    #[error("an include was requested without a filesystem context")]
    IncludeRequested(ParsedPath),
}

pub fn process(input: &str, state: ProcessorState) -> ExpandStr {
    let file_id = FileId::new(0);
    let ast = parser::Parser::new(input).parse();
    ExpandStr {
        inner: ExpandOne::new((file_id, ast), state),
        final_state: None,
    }
}

pub struct ExpandStr {
    inner: ExpandOne,
    final_state: Option<ProcessorState>,
}

impl ExpandStr {
    pub fn tokenize(
        self,
        current_version: u16,
        target_vulkan: bool,
        registry: &crate::exts::Registry,
    ) -> crate::last::Tokenizer<'_, Self> {
        crate::last::Tokenizer::new(self, current_version, target_vulkan, registry)
    }

    pub fn into_state(mut self) -> Option<ProcessorState> {
        self.final_state.take()
    }
}

impl Iterator for ExpandStr {
    type Item = Result<Event, Located<ProcessStrError>>;

    fn next(&mut self) -> Option<Self::Item> {
        let event = self.inner.next()?;
        match event {
            ExpandEvent::Event(event) => Some(Ok(event)),
            ExpandEvent::EnterFile(node, path) => Some(Err(LocatedBuilder::new()
                .pos(node.text_range())
                .resolve_file(self.inner.location())
                .finish(ProcessStrError::IncludeRequested(path)))),
            ExpandEvent::Completed(state) => {
                self.final_state = Some(state);
                None
            }
        }
    }
}

impl LocatedIterator for ExpandStr {
    fn location(&self) -> &crate::processor::expand::ExpandLocation {
        self.inner.location()
    }
}

#[cfg(test)]
mod tests {
    fn assert_send<T: Send>() {}

    #[test]
    fn test_error_send() {
        assert_send::<super::ProcessStrError>();
    }
}