ngvfs_docs.typ 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. #import "../docs_common/template/template.typ" : ZRYGenericDocs
  2. #import "@preview/tablex:0.0.8": tablex, colspanx, rowspanx
  3. #import "@preview/oxifmt:0.2.0": strfmt
  4. #let pageCounting = locate(loc=>counter(page).final(loc).at(0))
  5. #let title = "openNGVFS 文档"
  6. #let version = (
  7. major: 1,
  8. minor: 1,
  9. patch: 0,
  10. )
  11. #let semVerStr = strfmt("{}.{}.{}", version.major, version.minor, version.patch)
  12. #show: body => ZRYGenericDocs(
  13. title: title,
  14. subTitle: "",
  15. titleDesc: "",
  16. docVer: "API Ver. " + semVerStr,
  17. headerSettings: (
  18. enable: true,
  19. ascent: 20%,
  20. content: locate(loc => {
  21. let elems = query(selector(heading).before(loc), loc)
  22. if counter(page).at(loc).first() > 1 [
  23. #text(
  24. weight: "bold",
  25. size: 0.9em,
  26. )[
  27. #title
  28. ]
  29. #h(1fr)
  30. #text(
  31. weight: "thin",
  32. size: 0.7em,
  33. )[
  34. #counter(page).display() / #pageCounting
  35. ]
  36. #line(length: 100%)
  37. ]
  38. }),
  39. ),
  40. footerSettings: (
  41. enable: true,
  42. descent: 30%,
  43. content: locate(loc => {
  44. if counter(page).at(loc).first() > 1 [
  45. #line(length: 100%)
  46. #text(
  47. weight: "thin",
  48. size: 0.6em,
  49. )[
  50. 公开文档
  51. ]
  52. ]
  53. }),
  54. ),
  55. body
  56. )
  57. = 项目说明
  58. 该项目基于商业项目ProjectNagae下属的NagaeVFS V1.1.0,为NagaeVFS的开源版本。该版本使用MIT License开源。注意,NagaeVFS后续版本将不再与openNGVFS兼容。
  59. = 版本说明
  60. 当前版本从NagaeVFS V1.1.0衍生,经过一定程度的测试,但使用前请自行进行必要的功能测试。
  61. 当前版本提供以下功能。
  62. == VFS
  63. 一个可挂载的虚拟文件系统。其主机接口兼容afero.Fs。
  64. == INIT WASM
  65. 用于初始化文件系统挂载的WASM虚拟机。
  66. 该虚拟机提供以下接口:
  67. + 在主机上创建和释放afero.Fs对象的接口。
  68. + 挂载主机上被创建的afero.Fs对象的接口。
  69. + 在主机VFS上创建目录的接口。
  70. + 读取配置文件中ExKV键值对内容的接口。
  71. === 可创建的afs对象
  72. ==== 来自afero.Fs的类型
  73. 当前版本可创建的afero.Fs对象,由afero包本身提供的有:
  74. - afero.OsFs
  75. - afero.MemMapFs
  76. - afero.BasePathFs
  77. - afero.RegexpFs
  78. - afero.ReadOnlyFs
  79. - afero.CopyOnWriteFs
  80. - afero.CacheOnReadFs
  81. 其中经过简单测试并通过的有:
  82. - afero.OsFs
  83. - afero.MemMapFs
  84. - afero.BasePathFs
  85. - afero.ReadOnlyFs
  86. 其中经过测试有问题的:
  87. - afero.RegexpFs
  88. - Readdir功能在遇到无法匹配的文件时产生error
  89. 该问题来自afero.RegexpFs本身,故不提供其修正。
  90. 谨慎考虑使用RegexpFs。
  91. ==== 来自第三方的
  92. - `"github.com/bep/overlayfs" overlayfs.OverlayFs`
  93. 经过测试,但有如下问题:
  94. - 不支持在子目录下创建文件,会产生错误
  95. `The system cannot find the path specified.`
  96. = INIT WASI接口
  97. == WASM导出函数
  98. #{
  99. let data = yaml("init_wasi_export.yaml")
  100. for funcPair in data {
  101. {
  102. let funcName = funcPair.at(0)
  103. [==== 函数 #raw(funcName)]
  104. let funcPart = funcPair.at(1)
  105. let funcParams = funcPart.at("params", default: none)
  106. let funcResults = funcPart.at("results", default: none)
  107. let prototypeParams = if funcParams != none and funcParams.len() > 0 {
  108. let prototypeParamsList = ()
  109. for iParam in funcParams {
  110. prototypeParamsList.push(iParam.name + ": " + iParam.type)
  111. }
  112. prototypeParamsList.join(",")
  113. }else{""}
  114. let prototypeCode = "fn " + funcName + "(" + prototypeParams + ")"
  115. let prototypeResult = if funcResults != none and funcResults.len() > 0 {
  116. let prototypeResultList = ()
  117. for iResult in funcResults {
  118. prototypeResultList.push(iResult.name + ": " + iResult.type)
  119. }
  120. " -> (" + prototypeResultList.join(",") + ")"
  121. }else{""}
  122. prototypeCode = prototypeCode + prototypeResult + ";"
  123. let prototype = raw(prototypeCode, lang:"rust")
  124. let tableContent = (
  125. [*名称*], colspanx(4)[#funcPair.at(0)],
  126. [*说明*], colspanx(4)[#funcPart.desc],
  127. [*原型*], colspanx(4)[#prototype],
  128. )
  129. if funcParams != none and funcParams.len() > 0 {
  130. let lenParams = funcParams.len()
  131. tableContent.push(rowspanx(lenParams+1)[*参数*])
  132. tableContent.push([*名称*])
  133. tableContent.push([*WASM类型*])
  134. tableContent.push([*语义类型*])
  135. tableContent.push([*说明*])
  136. for param in funcParams {
  137. let paramEnum = param.at("enum", default: none)
  138. tableContent.push(param.name)
  139. tableContent.push(param.type)
  140. tableContent.push(if param.xtyp != none {param.xtyp} else {param.type})
  141. tableContent.push(
  142. if paramEnum != none [
  143. #param.desc
  144. #let paramEnumTable = ()
  145. #for peti in paramEnum {
  146. paramEnumTable.push(peti.at(0))
  147. paramEnumTable.push(peti.at(1))
  148. }
  149. #tablex(
  150. columns: 2,
  151. [*值*], [*说明*],
  152. ..paramEnumTable
  153. )
  154. ]else[#param.desc]
  155. )
  156. }
  157. }
  158. if funcResults != none and funcResults.len() > 0 {
  159. let lenResults = funcResults.len()
  160. tableContent.push(rowspanx(lenResults+1)[*返回值*])
  161. tableContent.push([*名称*])
  162. tableContent.push([*WASM类型*])
  163. tableContent.push([*语义类型*])
  164. tableContent.push([*说明*])
  165. for param in funcResults {
  166. let paramEnum = param.at("enum", default: none)
  167. let paramXtyp = param.at("xtyp", default: none)
  168. tableContent.push(param.name)
  169. tableContent.push(param.type)
  170. tableContent.push(if paramXtyp != none {paramXtyp} else {param.type})
  171. tableContent.push(
  172. if paramEnum != none [
  173. #param.desc
  174. #let paramEnumTable = ()
  175. #for peti in paramEnum {
  176. paramEnumTable.push(peti.at(0))
  177. paramEnumTable.push(peti.at(1))
  178. }
  179. #tablex(
  180. columns: 2,
  181. [*值*], [*说明*],
  182. ..paramEnumTable
  183. )
  184. ]else[#param.desc]
  185. )
  186. }
  187. }
  188. tablex(
  189. columns: 5,
  190. ..tableContent
  191. )
  192. }
  193. }
  194. }
  195. == 主机导出模块
  196. #{
  197. let data = yaml("init_wasi_import.yaml")
  198. for modPair in data {
  199. [=== 模块 #raw(modPair.at(0))]
  200. for funcPair in modPair.at(1) {
  201. {
  202. let funcName = funcPair.at(0)
  203. [==== 函数 #raw(funcName)]
  204. let funcPart = funcPair.at(1)
  205. let funcParams = funcPart.at("params", default: none)
  206. let funcResults = funcPart.at("results", default: none)
  207. let prototypeParams = if funcParams != none and funcParams.len() > 0 {
  208. let prototypeParamsList = ()
  209. for iParam in funcParams {
  210. prototypeParamsList.push(iParam.name + ": " + iParam.type)
  211. }
  212. prototypeParamsList.join(",")
  213. }else{""}
  214. let prototypeCode = "fn " + funcName + "(" + prototypeParams + ")"
  215. let prototypeResult = if funcResults != none and funcResults.len() > 0 {
  216. let prototypeResultList = ()
  217. for iResult in funcResults {
  218. prototypeResultList.push(iResult.name + ": " + iResult.type)
  219. }
  220. " -> (" + prototypeResultList.join(",") + ")"
  221. }else{""}
  222. prototypeCode = prototypeCode + prototypeResult + ";"
  223. let prototype = raw(prototypeCode, lang:"rust")
  224. let tableContent = (
  225. [*名称*], colspanx(4)[#funcPair.at(0)],
  226. [*说明*], colspanx(4)[#funcPart.desc],
  227. [*原型*], colspanx(4)[#prototype],
  228. )
  229. if funcParams != none and funcParams.len() > 0 {
  230. let lenParams = funcParams.len()
  231. tableContent.push(rowspanx(lenParams+1)[*参数*])
  232. tableContent.push([*名称*])
  233. tableContent.push([*WASM类型*])
  234. tableContent.push([*语义类型*])
  235. tableContent.push([*说明*])
  236. for param in funcParams {
  237. let paramEnum = param.at("enum", default: none)
  238. let paramXtyp = param.at("xtyp", default: none)
  239. tableContent.push(param.name)
  240. tableContent.push(param.type)
  241. tableContent.push(if paramXtyp != none {paramXtyp} else {param.type})
  242. tableContent.push(
  243. if paramEnum != none [
  244. #param.desc
  245. #let paramEnumTable = ()
  246. #for peti in paramEnum {
  247. paramEnumTable.push(peti.at(0))
  248. paramEnumTable.push(peti.at(1))
  249. }
  250. #tablex(
  251. columns: 2,
  252. [*值*], [*说明*],
  253. ..paramEnumTable
  254. )
  255. ]else[#param.desc]
  256. )
  257. }
  258. }
  259. if funcResults != none and funcResults.len() > 0 {
  260. let lenResults = funcResults.len()
  261. tableContent.push(rowspanx(lenResults+1)[*返回值*])
  262. tableContent.push([*名称*])
  263. tableContent.push([*WASM类型*])
  264. tableContent.push([*语义类型*])
  265. tableContent.push([*说明*])
  266. for param in funcResults {
  267. let paramEnum = param.at("enum", default: none)
  268. tableContent.push(param.name)
  269. tableContent.push(param.type)
  270. tableContent.push(if param.xtyp != none {param.xtyp} else {param.type})
  271. tableContent.push(
  272. if paramEnum != none [
  273. #param.desc
  274. #let paramEnumTable = ()
  275. #for peti in paramEnum {
  276. paramEnumTable.push(peti.at(0))
  277. paramEnumTable.push(peti.at(1))
  278. }
  279. #tablex(
  280. columns: 2,
  281. [*值*], [*说明*],
  282. ..paramEnumTable
  283. )
  284. ]else[#param.desc]
  285. )
  286. }
  287. }
  288. tablex(
  289. columns: 5,
  290. ..tableContent
  291. )
  292. }
  293. }
  294. }
  295. }
  296. == WASM侧Rust Crate
  297. 提供有用于WASM侧的接口包装Rust Crate。
  298. 目前本文档内暂不提供该Crate的文档。
  299. 该包的交互式文档可使用rustdoc生成:
  300. ```bash
  301. cd init-wasm
  302. just doc_html
  303. ```
  304. 生成的文档在`init-wasm/ngvfs_init_wasm_lib/target/doc/ngvfs_init_wasm_lib`
  305. 若安装有`SimpleHttpTestServer`,可继续使用如下命令:
  306. ```bash
  307. # 端口号可换成其他值
  308. just serv_doc "localhost:8088"
  309. ```
  310. 然后使用浏览器打开 #link("http://localhsot:8088/")。