1
1
use crate :: CargoResult ;
2
2
3
+ type Span = std:: ops:: Range < usize > ;
4
+
3
5
#[ derive( Debug ) ]
4
6
pub struct ScriptSource < ' s > {
5
- shebang : Option < & ' s str > ,
6
- info : Option < & ' s str > ,
7
- frontmatter : Option < & ' s str > ,
8
- content : & ' s str ,
7
+ raw : & ' s str ,
8
+ shebang : Option < Span > ,
9
+ info : Option < Span > ,
10
+ frontmatter : Option < Span > ,
11
+ content : Span ,
9
12
}
10
13
11
14
impl < ' s > ScriptSource < ' s > {
12
- pub fn parse ( input : & ' s str ) -> CargoResult < Self > {
15
+ pub fn parse ( raw : & ' s str ) -> CargoResult < Self > {
13
16
use winnow:: stream:: FindSlice as _;
17
+ use winnow:: stream:: Location as _;
18
+ use winnow:: stream:: Offset as _;
14
19
use winnow:: stream:: Stream as _;
15
20
21
+ let content_end = raw. len ( ) ;
16
22
let mut source = Self {
23
+ raw,
17
24
shebang : None ,
18
25
info : None ,
19
26
frontmatter : None ,
20
- content : input ,
27
+ content : 0 ..content_end ,
21
28
} ;
22
29
23
- let mut input = winnow:: stream:: LocatingSlice :: new ( input ) ;
30
+ let mut input = winnow:: stream:: LocatingSlice :: new ( raw ) ;
24
31
25
32
if let Some ( shebang_end) = strip_shebang ( input. as_ref ( ) ) {
26
- source. shebang = Some ( input. next_slice ( shebang_end) ) ;
27
- source. content = input. as_ref ( ) ;
33
+ let shebang_start = input. current_token_start ( ) ;
34
+ let _ = input. next_slice ( shebang_end) ;
35
+ let shebang_end = input. current_token_start ( ) ;
36
+ source. shebang = Some ( shebang_start..shebang_end) ;
37
+ source. content = shebang_end..content_end;
28
38
}
29
39
30
40
// Whitespace may precede a frontmatter but must end with a newline
@@ -58,35 +68,37 @@ impl<'s> ScriptSource<'s> {
58
68
let info = input. next_slice ( info_nl. start ) ;
59
69
let info = info. trim_matches ( is_whitespace) ;
60
70
if !info. is_empty ( ) {
61
- source. info = Some ( info) ;
71
+ let info_start = info. offset_from ( & raw ) ;
72
+ let info_end = info_start + info. len ( ) ;
73
+ source. info = Some ( info_start..info_end) ;
62
74
}
63
75
64
76
// Ends with a line that starts with a matching number of `-` only followed by whitespace
65
77
let nl_fence_pattern = format ! ( "\n {fence_pattern}" ) ;
66
78
let Some ( frontmatter_nl) = input. find_slice ( nl_fence_pattern. as_str ( ) ) else {
67
79
anyhow:: bail!( "no closing `{fence_pattern}` found for frontmatter" ) ;
68
80
} ;
69
- let frontmatter = input. next_slice ( frontmatter_nl. start + 1 ) ;
70
- let frontmatter = frontmatter
71
- . strip_prefix ( '\n' )
72
- . expect ( "earlier `found` + `split_at` left us here" ) ;
73
- source. frontmatter = Some ( frontmatter) ;
81
+ let frontmatter_start = input. current_token_start ( ) + 1 ; // skip nl from infostring
82
+ let _ = input. next_slice ( frontmatter_nl. start + 1 ) ;
83
+ let frontmatter_end = input. current_token_start ( ) ;
84
+ source. frontmatter = Some ( frontmatter_start..frontmatter_end) ;
74
85
let _ = input. next_slice ( fence_length) ;
75
86
76
87
let nl = input. find_slice ( "\n " ) ;
77
88
let after_closing_fence = input. next_slice (
78
89
nl. map ( |span| span. end )
79
90
. unwrap_or_else ( || input. eof_offset ( ) ) ,
80
91
) ;
92
+ let content_start = input. current_token_start ( ) ;
81
93
let after_closing_fence = after_closing_fence. trim_matches ( is_whitespace) ;
82
94
if !after_closing_fence. is_empty ( ) {
83
95
// extra characters beyond the original fence pattern, even if they are extra `-`
84
96
anyhow:: bail!( "trailing characters found after frontmatter close" ) ;
85
97
}
86
98
87
- source. content = input . finish ( ) ;
99
+ source. content = content_start..content_end ;
88
100
89
- let repeat = Self :: parse ( source. content ) ?;
101
+ let repeat = Self :: parse ( source. content ( ) ) ?;
90
102
if repeat. frontmatter . is_some ( ) {
91
103
anyhow:: bail!( "only one frontmatter is supported" ) ;
92
104
}
@@ -95,19 +107,19 @@ impl<'s> ScriptSource<'s> {
95
107
}
96
108
97
109
pub fn shebang ( & self ) -> Option < & ' s str > {
98
- self . shebang
110
+ self . shebang . clone ( ) . map ( |span| & self . raw [ span ] )
99
111
}
100
112
101
113
pub fn info ( & self ) -> Option < & ' s str > {
102
- self . info
114
+ self . info . clone ( ) . map ( |span| & self . raw [ span ] )
103
115
}
104
116
105
117
pub fn frontmatter ( & self ) -> Option < & ' s str > {
106
- self . frontmatter
118
+ self . frontmatter . clone ( ) . map ( |span| & self . raw [ span ] )
107
119
}
108
120
109
121
pub fn content ( & self ) -> & ' s str {
110
- self . content
122
+ & self . raw [ self . content . clone ( ) ]
111
123
}
112
124
}
113
125
0 commit comments