Reader.fs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547
  1. namespace FSharp.Data.Tdms
  2. open System
  3. open System.Buffers
  4. open System.IO
  5. open System.Numerics
  6. open System.Runtime.InteropServices
  7. open System.Text
  8. module Reader =
  9. type CastMemoryManager<'tfrom, 'tto when 'tfrom: struct and 'tfrom: (new: unit -> 'tfrom) and 'tfrom :> ValueType and 'tto: struct and 'tto: (new: unit
  10. -> 'tto) and 'tto :> ValueType>(memory: Memory<'tfrom>) =
  11. inherit MemoryManager<'tto>()
  12. override _.GetSpan() =
  13. MemoryMarshal.Cast<'tfrom, 'tto> memory.Span
  14. override _.Dispose _ = ()
  15. override _.Pin _ = raise (NotSupportedException())
  16. override _.Unpin() = raise (NotSupportedException())
  17. let cast<'tfrom, 'tto when 'tfrom: struct and 'tfrom: (new: unit -> 'tfrom) and 'tfrom :> ValueType and 'tto: struct and 'tto: (new: unit
  18. -> 'tto) and 'tto :> ValueType>
  19. (memory: Memory<'tfrom>)
  20. =
  21. if typeof<'tfrom> = typeof<'tto> then
  22. box memory :?> Memory<'tto>
  23. else
  24. (new CastMemoryManager<'tfrom, 'tto>(memory))
  25. .Memory
  26. let readPrimitiveRawData<'t when 't: struct and 't: (new: unit -> 't) and 't :> ValueType>
  27. (stream: Stream)
  28. (segments: PrimitiveRawDataBlock seq)
  29. bigEndian
  30. =
  31. let mutable position = 0
  32. let size = sizeof<'t>
  33. let data =
  34. Seq.sumBy
  35. (function
  36. | DecimatedPrimitiveRawDataBlock (_, size) -> size
  37. | InterleavedPrimitiveRawDataBlock { Count = count } -> count)
  38. segments
  39. |> int
  40. |> Array.zeroCreate<'t>
  41. let span =
  42. MemoryMarshal.Cast<'t, byte>(data.AsSpan())
  43. for segment in segments do
  44. match segment with
  45. | DecimatedPrimitiveRawDataBlock (start, length) ->
  46. stream.Seek(int64 start, SeekOrigin.Begin)
  47. |> ignore
  48. stream.Read(span.Slice(position * size, int length * size))
  49. |> ignore
  50. position <- position + int length
  51. | InterleavedPrimitiveRawDataBlock { Start = start
  52. Count = count
  53. Skip = skip } ->
  54. stream.Seek(int64 start, SeekOrigin.Begin)
  55. |> ignore
  56. for _ = 0 to int count - 1 do
  57. stream.Read(span.Slice(position * size, size))
  58. |> ignore
  59. stream.Seek(int64 skip, SeekOrigin.Current)
  60. |> ignore
  61. position <- position + 1
  62. if bigEndian && size > 1 then
  63. span.Reverse()
  64. Array.Reverse data
  65. data
  66. let readComplexRawData (stream: Stream) (segments: PrimitiveRawDataBlock seq) bigEndian =
  67. if not bigEndian then
  68. readPrimitiveRawData<Complex> stream segments false
  69. else
  70. let mutable position = 0
  71. let size = sizeof<Complex>
  72. let data =
  73. Seq.sumBy
  74. (function
  75. | DecimatedPrimitiveRawDataBlock (_, size) -> size
  76. | InterleavedPrimitiveRawDataBlock { Count = count } -> count)
  77. segments
  78. |> int
  79. |> Array.zeroCreate<Complex>
  80. let span =
  81. MemoryMarshal.Cast<Complex, byte>(data.AsSpan())
  82. for segment in segments do
  83. match segment with
  84. | DecimatedPrimitiveRawDataBlock (start, length) ->
  85. stream.Seek(int64 start, SeekOrigin.Begin)
  86. |> ignore
  87. stream.Read(span.Slice(position * size, int length * size))
  88. |> ignore
  89. position <- position + int length
  90. | InterleavedPrimitiveRawDataBlock { Start = start
  91. Count = count
  92. Skip = skip } ->
  93. stream.Seek(int64 start, SeekOrigin.Begin)
  94. |> ignore
  95. for _ = 0 to int count - 1 do
  96. stream.Read(span.Slice(position * size, size))
  97. |> ignore
  98. stream.Seek(int64 skip, SeekOrigin.Current)
  99. |> ignore
  100. position <- position + 1
  101. span.Reverse()
  102. MemoryMarshal
  103. .Cast<Complex, double>(data.AsSpan())
  104. .Reverse()
  105. data
  106. let readTimestampRawData (stream: Stream) (segments: PrimitiveRawDataBlock seq) bigEndian =
  107. if not bigEndian then
  108. readPrimitiveRawData<Timestamp> stream segments false
  109. else
  110. let mutable position = 0
  111. let size = sizeof<Timestamp>
  112. let data =
  113. Seq.sumBy
  114. (function
  115. | DecimatedPrimitiveRawDataBlock (_, size) -> size
  116. | InterleavedPrimitiveRawDataBlock { Count = count } -> count)
  117. segments
  118. |> int
  119. |> Array.zeroCreate<Timestamp>
  120. let span =
  121. MemoryMarshal.Cast<Timestamp, byte>(data.AsSpan())
  122. for segment in segments do
  123. match segment with
  124. | DecimatedPrimitiveRawDataBlock (start, length) ->
  125. stream.Seek(int64 start, SeekOrigin.Begin)
  126. |> ignore
  127. stream.Read(span.Slice(position * size, int length * size))
  128. |> ignore
  129. position <- position + int length
  130. | InterleavedPrimitiveRawDataBlock { Start = start
  131. Count = count
  132. Skip = skip } ->
  133. stream.Seek(int64 start, SeekOrigin.Begin)
  134. |> ignore
  135. for _ = 0 to int count - 1 do
  136. stream.Read(span.Slice(position * size, size))
  137. |> ignore
  138. stream.Seek(int64 skip, SeekOrigin.Current)
  139. |> ignore
  140. position <- position + 1
  141. span.Reverse()
  142. Array.Reverse data
  143. data
  144. let readFloat80RawData (stream: Stream) (segments: PrimitiveRawDataBlock seq) bigEndian =
  145. if not bigEndian then
  146. readPrimitiveRawData<float80> stream segments false
  147. else
  148. let mutable position = 0
  149. let size = sizeof<float80>
  150. let data =
  151. Seq.sumBy
  152. (function
  153. | DecimatedPrimitiveRawDataBlock (_, size) -> size
  154. | InterleavedPrimitiveRawDataBlock { Count = count } -> count)
  155. segments
  156. |> int
  157. |> Array.zeroCreate<float80>
  158. let span =
  159. MemoryMarshal.Cast<float80, byte>(data.AsSpan())
  160. for segment in segments do
  161. match segment with
  162. | DecimatedPrimitiveRawDataBlock (start, length) ->
  163. stream.Seek(int64 start, SeekOrigin.Begin)
  164. |> ignore
  165. stream.Read(span.Slice(position * size, int length * size))
  166. |> ignore
  167. position <- position + int length
  168. | InterleavedPrimitiveRawDataBlock { Start = start
  169. Count = count
  170. Skip = skip } ->
  171. stream.Seek(int64 start, SeekOrigin.Begin)
  172. |> ignore
  173. for _ = 0 to int count - 1 do
  174. stream.Read(span.Slice(position * size, size))
  175. |> ignore
  176. stream.Seek(int64 skip, SeekOrigin.Current)
  177. |> ignore
  178. position <- position + 1
  179. MemoryMarshal.Cast<byte, float80>(span).Reverse()
  180. Array.Reverse data
  181. data
  182. let readStringRawData (stream: Stream) (segments: (uint64 * uint64 * uint64) seq) bigEndian =
  183. let offsets =
  184. Seq.map (fun (_, length, _) -> length) segments
  185. |> Seq.max
  186. |> int
  187. |> ArrayPool<uint>.Shared.Rent
  188. let data =
  189. Seq.map (fun (_, _, bytes) -> bytes) segments
  190. |> Seq.max
  191. |> int
  192. |> ArrayPool<uint8>.Shared.Rent
  193. let strings =
  194. Seq.sumBy (fun (_, length, _) -> length) segments
  195. |> int
  196. |> Array.zeroCreate<string>
  197. let mutable position = 0
  198. for (start, length, bytes) in segments do
  199. stream.Seek(int64 start, SeekOrigin.Begin)
  200. |> ignore
  201. let offsetsSpan = offsets.AsSpan().Slice(0, int length)
  202. let offsetsByteSpan =
  203. MemoryMarshal.Cast<uint, uint8>(offsetsSpan)
  204. stream.Read(offsetsByteSpan) |> ignore
  205. if bigEndian then
  206. offsetsByteSpan.Reverse()
  207. offsetsSpan.Reverse()
  208. let mutable dataSpan = data.AsSpan().Slice(0, int bytes)
  209. stream.Read(dataSpan) |> ignore
  210. let mutable offset = 0
  211. for index = 0 to offsetsSpan.Length - 1 do
  212. strings.[position] <-
  213. Encoding.UTF8.GetString(
  214. dataSpan
  215. .Slice(0, int offsets.[index] - offset)
  216. .ToArray()
  217. )
  218. dataSpan <- dataSpan.Slice(int offsets.[index] - offset)
  219. offset <- int offsets.[index]
  220. position <- position + 1
  221. ArrayPool<byte>.Shared.Return(data, false)
  222. ArrayPool<uint>.Shared.Return(offsets, false)
  223. strings
  224. let readPrimitiveRawDataAsync<'t when 't: struct and 't: (new: unit -> 't) and 't :> ValueType>
  225. ct
  226. (stream: Stream)
  227. (segments: PrimitiveRawDataBlock seq)
  228. bigEndian
  229. =
  230. let mutable position = 0
  231. let size = sizeof<'t>
  232. let data =
  233. Seq.sumBy
  234. (function
  235. | DecimatedPrimitiveRawDataBlock (_, size) -> size
  236. | InterleavedPrimitiveRawDataBlock { Count = count } -> count)
  237. segments
  238. |> int
  239. |> Array.zeroCreate<'t>
  240. let memory = cast<'t, byte> (data.AsMemory())
  241. backgroundTask {
  242. for segment in segments do
  243. match segment with
  244. | DecimatedPrimitiveRawDataBlock (start, length) ->
  245. stream.Seek(int64 start, SeekOrigin.Begin)
  246. |> ignore
  247. let! _ = stream.ReadAsync(memory.Slice(position * size, int length * size), ct)
  248. position <- position + int length
  249. | InterleavedPrimitiveRawDataBlock { Start = start
  250. Count = count
  251. Skip = skip } ->
  252. stream.Seek(int64 start, SeekOrigin.Begin)
  253. |> ignore
  254. for _ = 0 to int count - 1 do
  255. let! _ = stream.ReadAsync(memory.Slice(position * size, size), ct)
  256. stream.Seek(int64 skip, SeekOrigin.Current)
  257. |> ignore
  258. position <- position + 1
  259. if bigEndian then
  260. memory.Span.Reverse()
  261. Array.Reverse data
  262. return data
  263. }
  264. let readFloat80RawDataAsync ct (stream: Stream) (segments: PrimitiveRawDataBlock seq) bigEndian =
  265. if not bigEndian then
  266. readPrimitiveRawDataAsync<float80> ct stream segments false
  267. else
  268. backgroundTask {
  269. let mutable position = 0
  270. let size = sizeof<float80>
  271. let data =
  272. Seq.sumBy
  273. (function
  274. | DecimatedPrimitiveRawDataBlock (_, size) -> size
  275. | InterleavedPrimitiveRawDataBlock { Count = count } -> count)
  276. segments
  277. |> int
  278. |> Array.zeroCreate<float80>
  279. let memory = cast<float80, byte> (data.AsMemory())
  280. for segment in segments do
  281. match segment with
  282. | DecimatedPrimitiveRawDataBlock (start, length) ->
  283. stream.Seek(int64 start, SeekOrigin.Begin)
  284. |> ignore
  285. let! _ = stream.ReadAsync(memory.Slice(position * size, int length * size), ct)
  286. position <- position + int length
  287. | InterleavedPrimitiveRawDataBlock { Start = start
  288. Count = count
  289. Skip = skip } ->
  290. stream.Seek(int64 start, SeekOrigin.Begin)
  291. |> ignore
  292. for _ = 0 to int count - 1 do
  293. let! _ = stream.ReadAsync(memory.Slice(position * size, size), ct)
  294. stream.Seek(int64 skip, SeekOrigin.Current)
  295. |> ignore
  296. position <- position + 1
  297. MemoryMarshal
  298. .Cast<byte, float80>(memory.Span)
  299. .Reverse()
  300. Array.Reverse data
  301. return data
  302. }
  303. let readComplexRawDataAsync ct (stream: Stream) (segments: PrimitiveRawDataBlock seq) bigEndian =
  304. if not bigEndian then
  305. readPrimitiveRawDataAsync<Complex> ct stream segments false
  306. else
  307. let mutable position = 0
  308. let size = sizeof<Complex>
  309. let data =
  310. Seq.sumBy
  311. (function
  312. | DecimatedPrimitiveRawDataBlock (_, size) -> size
  313. | InterleavedPrimitiveRawDataBlock { Count = count } -> count)
  314. segments
  315. |> int
  316. |> Array.zeroCreate<Complex>
  317. let memory = cast<Complex, byte> (data.AsMemory())
  318. backgroundTask {
  319. for segment in segments do
  320. match segment with
  321. | DecimatedPrimitiveRawDataBlock (start, length) ->
  322. stream.Seek(int64 start, SeekOrigin.Begin)
  323. |> ignore
  324. let! _ = stream.ReadAsync(memory.Slice(position * size, int length * size), ct)
  325. position <- position + int length
  326. | InterleavedPrimitiveRawDataBlock { Start = start
  327. Count = count
  328. Skip = skip } ->
  329. stream.Seek(int64 start, SeekOrigin.Begin)
  330. |> ignore
  331. for _ = 0 to int count - 1 do
  332. let! _ = stream.ReadAsync(memory.Slice(position * size, size), ct)
  333. stream.Seek(int64 skip, SeekOrigin.Current)
  334. |> ignore
  335. position <- position + 1
  336. memory.Span.Reverse()
  337. cast<Complex, double>(data.AsMemory())
  338. .Span.Reverse()
  339. return data
  340. }
  341. let readTimestampRawDataAsync ct (stream: Stream) (segments: PrimitiveRawDataBlock seq) bigEndian =
  342. if not bigEndian then
  343. readPrimitiveRawDataAsync<Timestamp> ct stream segments false
  344. else
  345. let mutable position = 0
  346. let size = sizeof<Timestamp>
  347. let data =
  348. Seq.sumBy
  349. (function
  350. | DecimatedPrimitiveRawDataBlock (_, size) -> size
  351. | InterleavedPrimitiveRawDataBlock { Count = count } -> count)
  352. segments
  353. |> int
  354. |> Array.zeroCreate<Timestamp>
  355. let memory = cast<Timestamp, byte> (data.AsMemory())
  356. backgroundTask {
  357. for segment in segments do
  358. match segment with
  359. | DecimatedPrimitiveRawDataBlock (start, length) ->
  360. stream.Seek(int64 start, SeekOrigin.Begin)
  361. |> ignore
  362. let! _ = stream.ReadAsync(memory.Slice(position * size, int length * size), ct)
  363. position <- position + int length
  364. | InterleavedPrimitiveRawDataBlock { Start = start
  365. Count = count
  366. Skip = skip } ->
  367. stream.Seek(int64 start, SeekOrigin.Begin)
  368. |> ignore
  369. for _ = 0 to int count - 1 do
  370. let! _ = stream.ReadAsync(memory.Slice(position * size, size), ct)
  371. stream.Seek(int64 skip, SeekOrigin.Current)
  372. |> ignore
  373. position <- position + 1
  374. memory.Span.Reverse()
  375. Array.Reverse data
  376. return data
  377. }
  378. let readStringRawDataAsync ct (stream: Stream) (segments: (uint64 * uint64 * uint64) seq) bigEndian =
  379. backgroundTask {
  380. let offsets =
  381. Seq.map (fun (_, length, _) -> length) segments
  382. |> Seq.max
  383. |> int
  384. |> ArrayPool<uint>.Shared.Rent
  385. let data =
  386. Seq.map (fun (_, _, bytes) -> bytes) segments
  387. |> Seq.max
  388. |> int
  389. |> ArrayPool<uint8>.Shared.Rent
  390. let strings =
  391. Seq.sumBy (fun (_, length, _) -> length) segments
  392. |> int
  393. |> Array.zeroCreate<string>
  394. let mutable position = 0
  395. for (start, length, bytes) in segments do
  396. stream.Seek(int64 start, SeekOrigin.Begin)
  397. |> ignore
  398. let offsetsMemory = offsets.AsMemory().Slice(0, int length)
  399. let offsetsByteMemory = cast<uint, uint8> offsetsMemory
  400. let! _ = stream.ReadAsync(offsetsByteMemory, ct)
  401. if bigEndian then
  402. offsetsByteMemory.Span.Reverse()
  403. offsetsMemory.Span.Reverse()
  404. let mutable dataMemory = data.AsMemory().Slice(0, int bytes)
  405. let! _ = stream.ReadAsync(dataMemory, ct)
  406. let mutable offset = 0
  407. for index = 0 to offsetsMemory.Length - 1 do
  408. strings.[position] <-
  409. Encoding.UTF8.GetString(
  410. dataMemory
  411. .Slice(0, int offsets.[index] - offset)
  412. .ToArray()
  413. )
  414. dataMemory <- dataMemory.Slice(int offsets.[index] - offset)
  415. offset <- int offsets.[index]
  416. position <- position + 1
  417. ArrayPool<byte>.Shared.Return(data, false)
  418. ArrayPool<uint>.Shared.Return(offsets, false)
  419. return strings
  420. }