@@ -93,10 +93,39 @@ pub struct GrammarAsset {
9393/// 读取仓内固定清单,并检查来源、许可证及候选资产字节。
9494pub fn bundled_grammar_candidates ( ) -> Result < GrammarAssetManifest , String > {
9595 let manifest = parse_grammar_asset_manifest ( include_bytes ! ( "../../../grammars/manifest.json" ) ) ?;
96- let codegraph_license = include_bytes ! ( "../../../grammars/LICENSE.codegraph" ) ;
97- if digest ( codegraph_license) != CODEGRAPH_LICENSE_SHA256 {
96+ verify_codegraph_license ( ) ?;
97+ verify_dependency_license ( & manifest) ?;
98+ for asset in & manifest. assets {
99+ verify_bundled_asset ( asset) ?;
100+ }
101+ Ok ( manifest)
102+ }
103+
104+ /// 只核对指定内置 grammar 的字节与许可,供按需加载的语法工作进程使用。
105+ /// 参数为固定语言 ID;返回清单身份和静态 WASM 字节,未知语言返回错误。
106+ pub fn bundled_grammar_candidate ( language : & str ) -> Result < ( GrammarAsset , & ' static [ u8 ] ) , String > {
107+ let manifest = parse_grammar_asset_manifest ( include_bytes ! ( "../../../grammars/manifest.json" ) ) ?;
108+ let asset = manifest
109+ . assets
110+ . iter ( )
111+ . find ( |asset| asset. language == language)
112+ . ok_or ( "不支持的 grammar 语种" ) ?;
113+ verify_codegraph_license ( ) ?;
114+ if matches ! ( language, "objc" | "solidity" ) {
115+ verify_dependency_license ( & manifest) ?;
116+ }
117+ let wasm = verify_bundled_asset ( asset) ?;
118+ Ok ( ( asset. clone ( ) , wasm) )
119+ }
120+
121+ fn verify_codegraph_license ( ) -> Result < ( ) , String > {
122+ if digest ( include_bytes ! ( "../../../grammars/LICENSE.codegraph" ) ) != CODEGRAPH_LICENSE_SHA256 {
98123 return Err ( "CodeGraph 许可证字节与固定来源不符" . into ( ) ) ;
99124 }
125+ Ok ( ( ) )
126+ }
127+
128+ fn verify_dependency_license ( manifest : & GrammarAssetManifest ) -> Result < ( ) , String > {
100129 if digest ( include_bytes ! (
101130 "../../../grammars/LICENSE.tree-sitter-wasms"
102131 ) ) != manifest
@@ -106,90 +135,92 @@ pub fn bundled_grammar_candidates() -> Result<GrammarAssetManifest, String> {
106135 {
107136 return Err ( "依赖包许可证字节与固定来源不符" . into ( ) ) ;
108137 }
109- for asset in & manifest. assets {
110- let ( wasm, license) = match asset. language . as_str ( ) {
111- "c" => (
112- include_bytes ! ( "../../../grammars/c/parser.wasm" ) . as_slice ( ) ,
113- include_bytes ! ( "../../../grammars/c/LICENSE" ) . as_slice ( ) ,
114- ) ,
115- "cpp" => (
116- include_bytes ! ( "../../../grammars/cpp/parser.wasm" ) . as_slice ( ) ,
117- include_bytes ! ( "../../../grammars/cpp/LICENSE" ) . as_slice ( ) ,
118- ) ,
119- "csharp" => (
120- include_bytes ! ( "../../../grammars/csharp/parser.wasm" ) . as_slice ( ) ,
121- include_bytes ! ( "../../../grammars/csharp/LICENSE" ) . as_slice ( ) ,
122- ) ,
123- "go" => (
124- include_bytes ! ( "../../../grammars/go/parser.wasm" ) . as_slice ( ) ,
125- include_bytes ! ( "../../../grammars/go/LICENSE" ) . as_slice ( ) ,
126- ) ,
127- "javascript" => (
128- include_bytes ! ( "../../../grammars/javascript/parser.wasm" ) . as_slice ( ) ,
129- include_bytes ! ( "../../../grammars/javascript/LICENSE" ) . as_slice ( ) ,
130- ) ,
131- "lua" => (
132- include_bytes ! ( "../../../grammars/lua/parser.wasm" ) . as_slice ( ) ,
133- include_bytes ! ( "../../../grammars/lua/LICENSE" ) . as_slice ( ) ,
134- ) ,
135- "luau" => (
136- include_bytes ! ( "../../../grammars/luau/parser.wasm" ) . as_slice ( ) ,
137- include_bytes ! ( "../../../grammars/luau/LICENSE" ) . as_slice ( ) ,
138- ) ,
139- "java" => (
140- include_bytes ! ( "../../../grammars/java/parser.wasm" ) . as_slice ( ) ,
141- include_bytes ! ( "../../../grammars/java/LICENSE" ) . as_slice ( ) ,
142- ) ,
143- "typescript" => (
144- include_bytes ! ( "../../../grammars/typescript/parser.wasm" ) . as_slice ( ) ,
145- include_bytes ! ( "../../../grammars/typescript/LICENSE" ) . as_slice ( ) ,
146- ) ,
147- "python" => (
148- include_bytes ! ( "../../../grammars/python/parser.wasm" ) . as_slice ( ) ,
149- include_bytes ! ( "../../../grammars/python/LICENSE" ) . as_slice ( ) ,
150- ) ,
151- "tsx" => (
152- include_bytes ! ( "../../../grammars/tsx/parser.wasm" ) . as_slice ( ) ,
153- include_bytes ! ( "../../../grammars/typescript/LICENSE" ) . as_slice ( ) ,
154- ) ,
155- "zig" => (
156- include_bytes ! ( "../../../grammars/zig/parser.wasm" ) . as_slice ( ) ,
157- include_bytes ! ( "../../../grammars/zig/LICENSE" ) . as_slice ( ) ,
158- ) ,
159- "objc" => (
160- include_bytes ! ( "../../../grammars/objc/parser.wasm" ) . as_slice ( ) ,
161- include_bytes ! ( "../../../grammars/objc/LICENSE" ) . as_slice ( ) ,
162- ) ,
163- "solidity" => (
164- include_bytes ! ( "../../../grammars/solidity/parser.wasm" ) . as_slice ( ) ,
165- include_bytes ! ( "../../../grammars/solidity/LICENSE" ) . as_slice ( ) ,
166- ) ,
167- "rust" => (
168- include_bytes ! ( "../../../grammars/rust/parser.wasm" ) . as_slice ( ) ,
169- include_bytes ! ( "../../../grammars/rust/LICENSE" ) . as_slice ( ) ,
170- ) ,
171- _ => return Err ( "候选语言未知" . into ( ) ) ,
138+ Ok ( ( ) )
139+ }
140+
141+ fn verify_bundled_asset ( asset : & GrammarAsset ) -> Result < & ' static [ u8 ] , String > {
142+ let ( wasm, license) = match asset. language . as_str ( ) {
143+ "c" => (
144+ include_bytes ! ( "../../../grammars/c/parser.wasm" ) . as_slice ( ) ,
145+ include_bytes ! ( "../../../grammars/c/LICENSE" ) . as_slice ( ) ,
146+ ) ,
147+ "cpp" => (
148+ include_bytes ! ( "../../../grammars/cpp/parser.wasm" ) . as_slice ( ) ,
149+ include_bytes ! ( "../../../grammars/cpp/LICENSE" ) . as_slice ( ) ,
150+ ) ,
151+ "csharp" => (
152+ include_bytes ! ( "../../../grammars/csharp/parser.wasm" ) . as_slice ( ) ,
153+ include_bytes ! ( "../../../grammars/csharp/LICENSE" ) . as_slice ( ) ,
154+ ) ,
155+ "go" => (
156+ include_bytes ! ( "../../../grammars/go/parser.wasm" ) . as_slice ( ) ,
157+ include_bytes ! ( "../../../grammars/go/LICENSE" ) . as_slice ( ) ,
158+ ) ,
159+ "javascript" => (
160+ include_bytes ! ( "../../../grammars/javascript/parser.wasm" ) . as_slice ( ) ,
161+ include_bytes ! ( "../../../grammars/javascript/LICENSE" ) . as_slice ( ) ,
162+ ) ,
163+ "lua" => (
164+ include_bytes ! ( "../../../grammars/lua/parser.wasm" ) . as_slice ( ) ,
165+ include_bytes ! ( "../../../grammars/lua/LICENSE" ) . as_slice ( ) ,
166+ ) ,
167+ "luau" => (
168+ include_bytes ! ( "../../../grammars/luau/parser.wasm" ) . as_slice ( ) ,
169+ include_bytes ! ( "../../../grammars/luau/LICENSE" ) . as_slice ( ) ,
170+ ) ,
171+ "java" => (
172+ include_bytes ! ( "../../../grammars/java/parser.wasm" ) . as_slice ( ) ,
173+ include_bytes ! ( "../../../grammars/java/LICENSE" ) . as_slice ( ) ,
174+ ) ,
175+ "typescript" => (
176+ include_bytes ! ( "../../../grammars/typescript/parser.wasm" ) . as_slice ( ) ,
177+ include_bytes ! ( "../../../grammars/typescript/LICENSE" ) . as_slice ( ) ,
178+ ) ,
179+ "python" => (
180+ include_bytes ! ( "../../../grammars/python/parser.wasm" ) . as_slice ( ) ,
181+ include_bytes ! ( "../../../grammars/python/LICENSE" ) . as_slice ( ) ,
182+ ) ,
183+ "tsx" => (
184+ include_bytes ! ( "../../../grammars/tsx/parser.wasm" ) . as_slice ( ) ,
185+ include_bytes ! ( "../../../grammars/typescript/LICENSE" ) . as_slice ( ) ,
186+ ) ,
187+ "zig" => (
188+ include_bytes ! ( "../../../grammars/zig/parser.wasm" ) . as_slice ( ) ,
189+ include_bytes ! ( "../../../grammars/zig/LICENSE" ) . as_slice ( ) ,
190+ ) ,
191+ "objc" => (
192+ include_bytes ! ( "../../../grammars/objc/parser.wasm" ) . as_slice ( ) ,
193+ include_bytes ! ( "../../../grammars/objc/LICENSE" ) . as_slice ( ) ,
194+ ) ,
195+ "solidity" => (
196+ include_bytes ! ( "../../../grammars/solidity/parser.wasm" ) . as_slice ( ) ,
197+ include_bytes ! ( "../../../grammars/solidity/LICENSE" ) . as_slice ( ) ,
198+ ) ,
199+ "rust" => (
200+ include_bytes ! ( "../../../grammars/rust/parser.wasm" ) . as_slice ( ) ,
201+ include_bytes ! ( "../../../grammars/rust/LICENSE" ) . as_slice ( ) ,
202+ ) ,
203+ _ => return Err ( "候选语言未知" . into ( ) ) ,
204+ } ;
205+ verify_grammar_asset ( asset, wasm, license) ?;
206+ if asset. language == "zig"
207+ && crate :: adapt_zig_wasm ( include_bytes ! ( "../../../grammars/zig/source.wasm" ) ) ? != wasm
208+ {
209+ return Err ( "Zig grammar 来源适配关系不符" . into ( ) ) ;
210+ }
211+ if matches ! ( asset. language. as_str( ) , "objc" | "solidity" ) {
212+ let source = if asset. language == "objc" {
213+ include_bytes ! ( "../../../grammars/objc/source.wasm" ) . as_slice ( )
214+ } else {
215+ include_bytes ! ( "../../../grammars/solidity/source.wasm" ) . as_slice ( )
172216 } ;
173- verify_grammar_asset ( asset, wasm, license) ?;
174- if asset. language == "zig"
175- && crate :: adapt_zig_wasm ( include_bytes ! ( "../../../grammars/zig/source.wasm" ) ) ? != wasm
217+ if asset. source_sha256 . as_deref ( ) != Some ( digest ( source) . as_str ( ) )
218+ || crate :: adapt_legacy_dylink ( & asset. language , source) ? != wasm
176219 {
177- return Err ( "Zig grammar 来源适配关系不符" . into ( ) ) ;
178- }
179- if matches ! ( asset. language. as_str( ) , "objc" | "solidity" ) {
180- let source = if asset. language == "objc" {
181- include_bytes ! ( "../../../grammars/objc/source.wasm" ) . as_slice ( )
182- } else {
183- include_bytes ! ( "../../../grammars/solidity/source.wasm" ) . as_slice ( )
184- } ;
185- if asset. source_sha256 . as_deref ( ) != Some ( digest ( source) . as_str ( ) )
186- || crate :: adapt_legacy_dylink ( & asset. language , source) ? != wasm
187- {
188- return Err ( "依赖 grammar 来源适配关系不符" . into ( ) ) ;
189- }
220+ return Err ( "依赖 grammar 来源适配关系不符" . into ( ) ) ;
190221 }
191222 }
192- Ok ( manifest )
223+ Ok ( wasm )
193224}
194225
195226/// 解析来源固定的候选清单;拒绝重复字段、漂移来源和伪造的已验收状态。
0 commit comments