Channel.fs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. namespace FSharp.Data.Tdms
  2. open System
  3. open System.IO
  4. open System.Numerics
  5. open System.Threading
  6. open System.Threading.Tasks
  7. type Channel = {
  8. Name: string
  9. FilePath: string
  10. Properties: Property seq
  11. RawDataBlocks: RawDataBlocks option
  12. BigEndian: bool
  13. }
  14. module Channel =
  15. let tryGetPropertyValue<'t> propertyName { Properties = properties } =
  16. properties
  17. |> Seq.tryFind (fun { Name = propertyName' } -> propertyName' = propertyName)
  18. |> Option.bind Property.tryGet<'t>
  19. let getPropertyValue<'t> propertyName =
  20. tryGetPropertyValue<'t> propertyName >> Option.get
  21. let tryGetRawData<'t>
  22. { FilePath = path
  23. RawDataBlocks = rawDataBlocks
  24. BigEndian = bigEndian }
  25. =
  26. let bufferSize = 65_536
  27. match rawDataBlocks with
  28. | None -> None
  29. | Some (PrimitiveRawDataBlocks (ty, rawDataBlockArray)) ->
  30. if typeof<'t>.IsAssignableFrom ty then
  31. use fileStream =
  32. new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.None)
  33. if ty = typeof<bool> then
  34. Reader.readPrimitiveRawData<bool> fileStream rawDataBlockArray bigEndian
  35. |> box
  36. |> tryUnbox<'t []>
  37. elif ty = typeof<sbyte> then
  38. Reader.readPrimitiveRawData<sbyte> fileStream rawDataBlockArray bigEndian
  39. |> box
  40. |> tryUnbox<'t []>
  41. elif ty = typeof<int16> then
  42. Reader.readPrimitiveRawData<int16> fileStream rawDataBlockArray bigEndian
  43. |> box
  44. |> tryUnbox<'t []>
  45. elif ty = typeof<int> then
  46. Reader.readPrimitiveRawData<int> fileStream rawDataBlockArray bigEndian
  47. |> box
  48. |> tryUnbox<'t []>
  49. elif ty = typeof<int64> then
  50. Reader.readPrimitiveRawData<int64> fileStream rawDataBlockArray bigEndian
  51. |> box
  52. |> tryUnbox<'t []>
  53. elif ty = typeof<byte> then
  54. Reader.readPrimitiveRawData<byte> fileStream rawDataBlockArray bigEndian
  55. |> box
  56. |> tryUnbox<'t []>
  57. elif ty = typeof<uint16> then
  58. Reader.readPrimitiveRawData<uint16> fileStream rawDataBlockArray bigEndian
  59. |> box
  60. |> tryUnbox<'t []>
  61. elif ty = typeof<uint> then
  62. Reader.readPrimitiveRawData<uint> fileStream rawDataBlockArray bigEndian
  63. |> box
  64. |> tryUnbox<'t []>
  65. elif ty = typeof<uint64> then
  66. Reader.readPrimitiveRawData<uint64> fileStream rawDataBlockArray bigEndian
  67. |> box
  68. |> tryUnbox<'t []>
  69. elif ty = typeof<float32> then
  70. Reader.readPrimitiveRawData<float32> fileStream rawDataBlockArray bigEndian
  71. |> box
  72. |> tryUnbox<'t []>
  73. elif ty = typeof<float> then
  74. Reader.readPrimitiveRawData<float> fileStream rawDataBlockArray bigEndian
  75. |> box
  76. |> tryUnbox<'t []>
  77. elif ty = typeof<Complex> then
  78. Reader.readComplexRawData fileStream rawDataBlockArray bigEndian
  79. |> box
  80. |> tryUnbox<'t []>
  81. elif ty = typeof<Timestamp> then
  82. Reader.readTimestampRawData fileStream rawDataBlockArray bigEndian
  83. |> box
  84. |> tryUnbox<'t []>
  85. elif ty = typeof<float80> then
  86. Reader.readFloat80RawData fileStream rawDataBlockArray bigEndian
  87. |> box
  88. |> tryUnbox<'t []>
  89. else
  90. None
  91. else if ty = typeof<Timestamp> then
  92. if typeof<'t> = typeof<DateTime> then
  93. use fileStream =
  94. new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.None)
  95. Reader.readTimestampRawData fileStream rawDataBlockArray bigEndian
  96. |> Array.map Timestamp.toDateTime
  97. |> box
  98. |> tryUnbox<'t []>
  99. else if typeof<'t> = typeof<DateTimeOffset> then
  100. use fileStream =
  101. new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.None)
  102. Reader.readTimestampRawData fileStream rawDataBlockArray bigEndian
  103. |> Array.map Timestamp.toDateTimeOffset
  104. |> box
  105. |> tryUnbox<'t []>
  106. else if typeof<'t> = typeof<TimeSpan> then
  107. use fileStream =
  108. new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.None)
  109. Reader.readTimestampRawData fileStream rawDataBlockArray bigEndian
  110. |> Array.map Timestamp.toTimeSpan
  111. |> box
  112. |> tryUnbox<'t []>
  113. else
  114. None
  115. else
  116. None
  117. | Some (StringRawDataBlocks stringRawDataBlockArray) ->
  118. if typeof<'t> = typeof<string> then
  119. use fileStream =
  120. new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.None)
  121. Reader.readStringRawData fileStream stringRawDataBlockArray bigEndian
  122. |> box
  123. |> tryUnbox<'t []>
  124. else
  125. None
  126. #if !IS_DESIGNTIME
  127. let tryGetRawDataAsyncCt<'t>
  128. ct
  129. { FilePath = path
  130. RawDataBlocks = rawDataBlocks
  131. BigEndian = bigEndian }
  132. =
  133. let bufferSize = 65_536
  134. match rawDataBlocks with
  135. | None -> Task.FromResult None
  136. | Some (PrimitiveRawDataBlocks (ty, rawDataBlockArray)) ->
  137. if ty = typeof<'t> then
  138. if ty = typeof<bool> then
  139. backgroundTask {
  140. use fileStream =
  141. new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.Asynchronous)
  142. let! result = Reader.readPrimitiveRawDataAsync<bool> ct fileStream rawDataBlockArray bigEndian
  143. return box result |> tryUnbox<'t []>
  144. }
  145. else if ty = typeof<sbyte> then
  146. backgroundTask {
  147. use fileStream =
  148. new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.Asynchronous)
  149. let! result = Reader.readPrimitiveRawDataAsync<sbyte> ct fileStream rawDataBlockArray bigEndian
  150. return box result |> tryUnbox<'t []>
  151. }
  152. else if ty = typeof<int16> then
  153. backgroundTask {
  154. use fileStream =
  155. new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.Asynchronous)
  156. let! result = Reader.readPrimitiveRawDataAsync<int16> ct fileStream rawDataBlockArray bigEndian
  157. return box result |> tryUnbox<'t []>
  158. }
  159. else if ty = typeof<int> then
  160. backgroundTask {
  161. use fileStream =
  162. new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.Asynchronous)
  163. let! result = Reader.readPrimitiveRawDataAsync<int> ct fileStream rawDataBlockArray bigEndian
  164. return box result |> tryUnbox<'t []>
  165. }
  166. else if ty = typeof<int64> then
  167. backgroundTask {
  168. use fileStream =
  169. new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.Asynchronous)
  170. let! result = Reader.readPrimitiveRawDataAsync<int64> ct fileStream rawDataBlockArray bigEndian
  171. return box result |> tryUnbox<'t []>
  172. }
  173. else if ty = typeof<byte> then
  174. backgroundTask {
  175. use fileStream =
  176. new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.Asynchronous)
  177. let! result = Reader.readPrimitiveRawDataAsync<byte> ct fileStream rawDataBlockArray bigEndian
  178. return box result |> tryUnbox<'t []>
  179. }
  180. else if ty = typeof<uint16> then
  181. backgroundTask {
  182. use fileStream =
  183. new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.Asynchronous)
  184. let! result = Reader.readPrimitiveRawDataAsync<uint16> ct fileStream rawDataBlockArray bigEndian
  185. return box result |> tryUnbox<'t []>
  186. }
  187. else if ty = typeof<uint> then
  188. backgroundTask {
  189. use fileStream =
  190. new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.Asynchronous)
  191. let! result = Reader.readPrimitiveRawDataAsync<uint> ct fileStream rawDataBlockArray bigEndian
  192. return box result |> tryUnbox<'t []>
  193. }
  194. else if ty = typeof<uint64> then
  195. backgroundTask {
  196. use fileStream =
  197. new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.Asynchronous)
  198. let! result = Reader.readPrimitiveRawDataAsync<uint64> ct fileStream rawDataBlockArray bigEndian
  199. return box result |> tryUnbox<'t []>
  200. }
  201. else if ty = typeof<float32> then
  202. backgroundTask {
  203. use fileStream =
  204. new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.Asynchronous)
  205. let! result = Reader.readPrimitiveRawDataAsync<float32> ct fileStream rawDataBlockArray bigEndian
  206. return box result |> tryUnbox<'t []>
  207. }
  208. else if ty = typeof<float> then
  209. backgroundTask {
  210. use fileStream =
  211. new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.Asynchronous)
  212. let! result = Reader.readPrimitiveRawDataAsync<float> ct fileStream rawDataBlockArray bigEndian
  213. return box result |> tryUnbox<'t []>
  214. }
  215. else if ty = typeof<float80> then
  216. backgroundTask {
  217. use fileStream =
  218. new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.Asynchronous)
  219. let! result = Reader.readFloat80RawDataAsync ct fileStream rawDataBlockArray bigEndian
  220. return box result |> tryUnbox<'t []>
  221. }
  222. else if ty = typeof<Complex> then
  223. backgroundTask {
  224. use fileStream =
  225. new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.Asynchronous)
  226. let! result = Reader.readComplexRawDataAsync ct fileStream rawDataBlockArray bigEndian
  227. return box result |> tryUnbox<'t []>
  228. }
  229. else
  230. Task.FromResult None
  231. else if ty = typeof<Timestamp> then
  232. if typeof<'t> = typeof<DateTime> then
  233. backgroundTask {
  234. use fileStream =
  235. new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.Asynchronous)
  236. let! result = Reader.readTimestampRawDataAsync ct fileStream rawDataBlockArray bigEndian
  237. return
  238. Array.map Timestamp.toDateTime result
  239. |> box
  240. |> tryUnbox<'t []>
  241. }
  242. else if typeof<'t> = typeof<DateTimeOffset> then
  243. backgroundTask {
  244. use fileStream =
  245. new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.Asynchronous)
  246. let! result = Reader.readTimestampRawDataAsync ct fileStream rawDataBlockArray bigEndian
  247. return
  248. Array.map Timestamp.toDateTimeOffset result
  249. |> box
  250. |> tryUnbox<'t []>
  251. }
  252. else if typeof<'t> = typeof<TimeSpan> then
  253. backgroundTask {
  254. use fileStream =
  255. new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.Asynchronous)
  256. let! result = Reader.readTimestampRawDataAsync ct fileStream rawDataBlockArray bigEndian
  257. return
  258. Array.map Timestamp.toTimeSpan result
  259. |> box
  260. |> tryUnbox<'t []>
  261. }
  262. else
  263. Task.FromResult None
  264. else
  265. Task.FromResult None
  266. | Some (StringRawDataBlocks stringRawDataBlockArray) ->
  267. if typeof<'t> = typeof<string> then
  268. backgroundTask {
  269. use fileStream =
  270. new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.Asynchronous)
  271. let! result = Reader.readStringRawDataAsync ct fileStream stringRawDataBlockArray bigEndian
  272. return result |> box |> tryUnbox<'t []>
  273. }
  274. else
  275. Task.FromResult None
  276. let tryRawDataAsync<'t> = tryGetRawDataAsyncCt<'t> CancellationToken.None
  277. #endif