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
use crate::{MagicString, CowStr};

pub struct JoinerOptions {
    pub separator: Option<String>,
}

#[derive(Default)]
pub struct Joiner<'s> {
    sources: Vec<MagicString<'s>>,
    separator: Option<String>,
}

impl<'s> Joiner<'s> {
    // --- public
    pub fn new() -> Self {
        Self::default()
    }

    pub fn with_options(options: JoinerOptions) -> Self {
        Self {
            separator: options.separator,
            ..Default::default()
        }
    }

    pub fn append(&mut self, source: MagicString<'s>) -> &mut Self {
        self.sources.push(source);
        self
    }

    pub fn append_raw(&mut self, raw: impl Into<CowStr<'s>>) -> &mut Self {
        self.sources.push(MagicString::new(raw));
        self
    }

    pub fn len(&self) -> usize {
        self.fragments().map(|s| s.len()).sum()
    }

    pub fn join(&self) -> String {
        let mut ret = String::with_capacity(self.len());
        self.fragments().for_each(|frag| {
            ret.push_str(frag);
        });
        ret
    }

    // --- private

    fn fragments(&'s self) -> impl Iterator<Item = &'s str> {
        let mut iter = self
            .sources
            .iter()
            .flat_map(|c| self.separator.as_deref().into_iter().chain(c.fragments()));
        // Drop the first separator
        if self.separator.is_some() {
            iter.next();
        }
        iter
    }

    
}