siderust-js 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (272) hide show
  1. package/.github/workflows/ci.yml +166 -0
  2. package/.gitmodules +9 -0
  3. package/CHANGELOG.md +26 -0
  4. package/LICENSE +661 -0
  5. package/README.md +138 -0
  6. package/package.json +12 -0
  7. package/qtty-js/.github/workflows/ci.yml +151 -0
  8. package/qtty-js/.gitmodules +3 -0
  9. package/qtty-js/CHANGELOG.md +31 -0
  10. package/qtty-js/LICENSE +661 -0
  11. package/qtty-js/README.md +132 -0
  12. package/qtty-js/package.json +20 -0
  13. package/qtty-js/qtty/.github/workflows/ci.yml +155 -0
  14. package/qtty-js/qtty/CHANGELOG.md +120 -0
  15. package/qtty-js/qtty/Cargo.lock +1462 -0
  16. package/qtty-js/qtty/Cargo.toml +12 -0
  17. package/qtty-js/qtty/LICENSE +661 -0
  18. package/qtty-js/qtty/README.md +9 -0
  19. package/qtty-js/qtty/qtty/Cargo.toml +41 -0
  20. package/qtty-js/qtty/qtty/README.md +8 -0
  21. package/qtty-js/qtty/qtty/examples/angles.rs +14 -0
  22. package/qtty-js/qtty/qtty/examples/astronomy.rs +17 -0
  23. package/qtty-js/qtty/qtty/examples/dimensional_arithmetic.rs +83 -0
  24. package/qtty-js/qtty/qtty/examples/python_integration.rs +61 -0
  25. package/qtty-js/qtty/qtty/examples/quickstart.rs +15 -0
  26. package/qtty-js/qtty/qtty/examples/ratios.rs +12 -0
  27. package/qtty-js/qtty/qtty/examples/serde_with_unit.rs +234 -0
  28. package/qtty-js/qtty/qtty/examples/serialization.rs +141 -0
  29. package/qtty-js/qtty/qtty/examples/serialization_advanced.rs +155 -0
  30. package/qtty-js/qtty/qtty/src/f32.rs +108 -0
  31. package/qtty-js/qtty/qtty/src/f64.rs +30 -0
  32. package/qtty-js/qtty/qtty/src/i128.rs +111 -0
  33. package/qtty-js/qtty/qtty/src/i16.rs +111 -0
  34. package/qtty-js/qtty/qtty/src/i32.rs +111 -0
  35. package/qtty-js/qtty/qtty/src/i64.rs +111 -0
  36. package/qtty-js/qtty/qtty/src/i8.rs +111 -0
  37. package/qtty-js/qtty/qtty/src/lib.rs +238 -0
  38. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-no-std/Cargo.lock +83 -0
  39. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-no-std/Cargo.toml +10 -0
  40. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-no-std/src/lib.rs +7 -0
  41. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-no-std-alloc/Cargo.lock +83 -0
  42. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-no-std-alloc/Cargo.toml +10 -0
  43. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-no-std-alloc/src/lib.rs +7 -0
  44. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-std/Cargo.lock +83 -0
  45. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-std/Cargo.toml +10 -0
  46. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-std/src/lib.rs +5 -0
  47. package/qtty-js/qtty/qtty/tests/integration_tests.rs +529 -0
  48. package/qtty-js/qtty/qtty/tests/qtty_vec_feature_matrix.rs +58 -0
  49. package/qtty-js/qtty/qtty-core/Cargo.toml +41 -0
  50. package/qtty-js/qtty/qtty-core/README.md +8 -0
  51. package/qtty-js/qtty/qtty-core/examples/diesel_integration.rs +145 -0
  52. package/qtty-js/qtty/qtty-core/examples/quantity_db_serde.rs +215 -0
  53. package/qtty-js/qtty/qtty-core/src/dimension.rs +249 -0
  54. package/qtty-js/qtty/qtty-core/src/feature_diesel.rs +318 -0
  55. package/qtty-js/qtty/qtty-core/src/feature_pyo3.rs +27 -0
  56. package/qtty-js/qtty/qtty-core/src/feature_serde.rs +203 -0
  57. package/qtty-js/qtty/qtty-core/src/feature_tiberius.rs +28 -0
  58. package/qtty-js/qtty/qtty-core/src/lib.rs +744 -0
  59. package/qtty-js/qtty/qtty-core/src/macros.rs +93 -0
  60. package/qtty-js/qtty/qtty-core/src/quantity.rs +810 -0
  61. package/qtty-js/qtty/qtty-core/src/scalar.rs +1742 -0
  62. package/qtty-js/qtty/qtty-core/src/unit.rs +332 -0
  63. package/qtty-js/qtty/qtty-core/src/units/angular.rs +1228 -0
  64. package/qtty-js/qtty/qtty-core/src/units/area.rs +243 -0
  65. package/qtty-js/qtty/qtty-core/src/units/frequency.rs +179 -0
  66. package/qtty-js/qtty/qtty-core/src/units/length.rs +1270 -0
  67. package/qtty-js/qtty/qtty-core/src/units/mass.rs +488 -0
  68. package/qtty-js/qtty/qtty-core/src/units/mod.rs +26 -0
  69. package/qtty-js/qtty/qtty-core/src/units/power.rs +324 -0
  70. package/qtty-js/qtty/qtty-core/src/units/time.rs +667 -0
  71. package/qtty-js/qtty/qtty-core/src/units/unitless.rs +212 -0
  72. package/qtty-js/qtty/qtty-core/src/units/velocity.rs +210 -0
  73. package/qtty-js/qtty/qtty-core/src/units/volume.rs +269 -0
  74. package/qtty-js/qtty/qtty-core/tests/core.rs +628 -0
  75. package/qtty-js/qtty/qtty-core/tests/diesel.rs +461 -0
  76. package/qtty-js/qtty/qtty-core/tests/integers.rs +632 -0
  77. package/qtty-js/qtty/qtty-core/tests/no_cross_unit_ops.rs +35 -0
  78. package/qtty-js/qtty/qtty-core/tests/pyo3.rs +334 -0
  79. package/qtty-js/qtty/qtty-core/tests/quantity_f32.rs +276 -0
  80. package/qtty-js/qtty/qtty-core/tests/scalar_decimal.rs +258 -0
  81. package/qtty-js/qtty/qtty-core/tests/scalar_f32.rs +286 -0
  82. package/qtty-js/qtty/qtty-core/tests/scalar_f64_real.rs +287 -0
  83. package/qtty-js/qtty/qtty-core/tests/scalar_rational.rs +260 -0
  84. package/qtty-js/qtty/qtty-core/tests/serde.rs +256 -0
  85. package/qtty-js/qtty/qtty-core/tests/tiberius.rs +208 -0
  86. package/qtty-js/qtty/qtty-derive/Cargo.toml +23 -0
  87. package/qtty-js/qtty/qtty-derive/README.md +8 -0
  88. package/qtty-js/qtty/qtty-derive/src/lib.rs +340 -0
  89. package/qtty-js/qtty/qtty-ffi/ARCHITECTURE.md +3 -0
  90. package/qtty-js/qtty/qtty-ffi/Cargo.toml +31 -0
  91. package/qtty-js/qtty/qtty-ffi/README.md +9 -0
  92. package/qtty-js/qtty/qtty-ffi/build.rs +326 -0
  93. package/qtty-js/qtty/qtty-ffi/cbindgen.toml +105 -0
  94. package/qtty-js/qtty/qtty-ffi/include/qtty_ffi.h +1126 -0
  95. package/qtty-js/qtty/qtty-ffi/src/ffi.rs +1251 -0
  96. package/qtty-js/qtty/qtty-ffi/src/ffi_serde.rs +294 -0
  97. package/qtty-js/qtty/qtty-ffi/src/helpers.rs +310 -0
  98. package/qtty-js/qtty/qtty-ffi/src/lib.rs +229 -0
  99. package/qtty-js/qtty/qtty-ffi/src/macros.rs +121 -0
  100. package/qtty-js/qtty/qtty-ffi/src/registry.rs +274 -0
  101. package/qtty-js/qtty/qtty-ffi/src/types.rs +620 -0
  102. package/qtty-js/qtty/qtty-ffi/tests/integration_tests.rs +842 -0
  103. package/qtty-js/qtty/qtty-ffi/units.csv +156 -0
  104. package/qtty-js/qtty/qtty-ffi/units.csv.md +3 -0
  105. package/qtty-js/qtty-node/.prettierignore +6 -0
  106. package/qtty-js/qtty-node/.prettierrc.json +6 -0
  107. package/qtty-js/qtty-node/README.md +250 -0
  108. package/qtty-js/qtty-node/c8.config.json +11 -0
  109. package/qtty-js/qtty-node/eslint.config.js +31 -0
  110. package/qtty-js/qtty-node/examples/arithmetic.mjs +64 -0
  111. package/qtty-js/qtty-node/examples/astronomy.mjs +90 -0
  112. package/qtty-js/qtty-node/examples/quickstart.mjs +36 -0
  113. package/qtty-js/qtty-node/examples/serialization.mjs +125 -0
  114. package/qtty-js/qtty-node/examples/unit_factories.mjs +74 -0
  115. package/qtty-js/qtty-node/index.d.ts +219 -0
  116. package/qtty-js/qtty-node/index.js +323 -0
  117. package/qtty-js/qtty-node/lib/DerivedQuantity.js +122 -0
  118. package/qtty-js/qtty-node/lib/Quantity.js +151 -0
  119. package/qtty-js/qtty-node/lib/backend.js +25 -0
  120. package/qtty-js/qtty-node/native.cjs +306 -0
  121. package/qtty-js/qtty-node/package-lock.json +3223 -0
  122. package/qtty-js/qtty-node/package.json +70 -0
  123. package/qtty-js/qtty-node/units.d.ts +299 -0
  124. package/qtty-js/qtty-node/units.js +210 -0
  125. package/qtty-js/qtty-web/Cargo.lock +767 -0
  126. package/qtty-js/qtty-web/Cargo.toml +21 -0
  127. package/qtty-js/qtty-web/index.d.ts +140 -0
  128. package/qtty-js/qtty-web/index.js +20 -0
  129. package/qtty-js/qtty-web/lib/DerivedQuantity.js +58 -0
  130. package/qtty-js/qtty-web/lib/Quantity.js +75 -0
  131. package/qtty-js/qtty-web/lib/backend.js +80 -0
  132. package/qtty-js/qtty-web/package.json +45 -0
  133. package/qtty-js/qtty-web/src/lib.rs +111 -0
  134. package/qtty-js/scripts/ci.sh +73 -0
  135. package/scripts/ci.sh +123 -0
  136. package/siderust-core/Cargo.lock +787 -0
  137. package/siderust-core/Cargo.toml +18 -0
  138. package/siderust-core/DEDUPLICATION.md +124 -0
  139. package/siderust-core/src/body.rs +120 -0
  140. package/siderust-core/src/events.rs +184 -0
  141. package/siderust-core/src/lib.rs +20 -0
  142. package/siderust-core/src/observer.rs +55 -0
  143. package/siderust-core/src/position.rs +213 -0
  144. package/siderust-node/.prettierignore +7 -0
  145. package/siderust-node/.prettierrc.json +6 -0
  146. package/siderust-node/Cargo.lock +906 -0
  147. package/siderust-node/Cargo.toml +29 -0
  148. package/siderust-node/README.md +109 -0
  149. package/siderust-node/__test__/index.test.mjs +248 -0
  150. package/siderust-node/build.rs +5 -0
  151. package/siderust-node/c8.config.json +3 -0
  152. package/siderust-node/eslint.config.js +31 -0
  153. package/siderust-node/examples/01_basic_coordinates.mjs +24 -0
  154. package/siderust-node/examples/02_coordinate_transformations.mjs +25 -0
  155. package/siderust-node/examples/03_all_frames_conversions.mjs +26 -0
  156. package/siderust-node/examples/04_all_center_conversions.mjs +24 -0
  157. package/siderust-node/examples/05_target_tracking.mjs +22 -0
  158. package/siderust-node/examples/06_night_events.mjs +18 -0
  159. package/siderust-node/examples/07_moon_properties.mjs +21 -0
  160. package/siderust-node/examples/08_solar_system.mjs +19 -0
  161. package/siderust-node/examples/09_star_observability.mjs +22 -0
  162. package/siderust-node/examples/10_time_periods.mjs +9 -0
  163. package/siderust-node/examples/11_serialization.mjs +31 -0
  164. package/siderust-node/examples/12_runtime_ephemeris.mjs +27 -0
  165. package/siderust-node/examples/13_coordinate_operations.mjs +20 -0
  166. package/siderust-node/index.d.ts +623 -0
  167. package/siderust-node/index.js +79 -0
  168. package/siderust-node/lib/Observer.js +112 -0
  169. package/siderust-node/lib/Star.js +118 -0
  170. package/siderust-node/lib/backend.js +63 -0
  171. package/siderust-node/lib/wrappers.js +566 -0
  172. package/siderust-node/main.js +20 -0
  173. package/siderust-node/native.cjs +360 -0
  174. package/siderust-node/package-lock.json +3261 -0
  175. package/siderust-node/package.json +71 -0
  176. package/siderust-node/src/body.rs +74 -0
  177. package/siderust-node/src/coordinates.rs +372 -0
  178. package/siderust-node/src/ephemeris.rs +462 -0
  179. package/siderust-node/src/events.rs +577 -0
  180. package/siderust-node/src/lib.rs +43 -0
  181. package/siderust-node/src/observer.rs +132 -0
  182. package/siderust-node/src/phase.rs +218 -0
  183. package/siderust-node/src/position.rs +292 -0
  184. package/siderust-node/src/star.rs +200 -0
  185. package/siderust-web/Cargo.lock +855 -0
  186. package/siderust-web/Cargo.toml +34 -0
  187. package/siderust-web/README.md +100 -0
  188. package/siderust-web/__test__/index.test.mjs +118 -0
  189. package/siderust-web/examples/github-pages/README.md +31 -0
  190. package/siderust-web/examples/github-pages/index.html +135 -0
  191. package/siderust-web/index.d.ts +311 -0
  192. package/siderust-web/index.js +66 -0
  193. package/siderust-web/lib/Observer.js +103 -0
  194. package/siderust-web/lib/Star.js +116 -0
  195. package/siderust-web/lib/backend.js +400 -0
  196. package/siderust-web/lib/wrappers.js +512 -0
  197. package/siderust-web/package.json +55 -0
  198. package/siderust-web/src/body.rs +69 -0
  199. package/siderust-web/src/coordinates.rs +302 -0
  200. package/siderust-web/src/ephemeris.rs +456 -0
  201. package/siderust-web/src/events.rs +520 -0
  202. package/siderust-web/src/lib.rs +51 -0
  203. package/siderust-web/src/observer.rs +117 -0
  204. package/siderust-web/src/phase.rs +190 -0
  205. package/siderust-web/src/position.rs +291 -0
  206. package/siderust-web/src/star.rs +178 -0
  207. package/tempoch-js/.github/workflows/ci.yml +142 -0
  208. package/tempoch-js/.gitmodules +3 -0
  209. package/tempoch-js/CHANGELOG.md +25 -0
  210. package/tempoch-js/LICENSE +661 -0
  211. package/tempoch-js/README.md +126 -0
  212. package/tempoch-js/package.json +20 -0
  213. package/tempoch-js/scripts/ci.sh +73 -0
  214. package/tempoch-js/tempoch/.github/workflows/ci.yml +113 -0
  215. package/tempoch-js/tempoch/CHANGELOG.md +82 -0
  216. package/tempoch-js/tempoch/Cargo.lock +947 -0
  217. package/tempoch-js/tempoch/Cargo.toml +3 -0
  218. package/tempoch-js/tempoch/LICENSE +661 -0
  219. package/tempoch-js/tempoch/README.md +76 -0
  220. package/tempoch-js/tempoch/tempoch/Cargo.toml +27 -0
  221. package/tempoch-js/tempoch/tempoch/examples/periods.rs +45 -0
  222. package/tempoch-js/tempoch/tempoch/examples/quickstart.rs +13 -0
  223. package/tempoch-js/tempoch/tempoch/src/lib.rs +49 -0
  224. package/tempoch-js/tempoch/tempoch/tests/integration.rs +57 -0
  225. package/tempoch-js/tempoch/tempoch-core/Cargo.toml +24 -0
  226. package/tempoch-js/tempoch/tempoch-core/src/delta_t.rs +345 -0
  227. package/tempoch-js/tempoch/tempoch-core/src/instant.rs +811 -0
  228. package/tempoch-js/tempoch/tempoch-core/src/julian_date_ext.rs +142 -0
  229. package/tempoch-js/tempoch/tempoch-core/src/lib.rs +81 -0
  230. package/tempoch-js/tempoch/tempoch-core/src/period.rs +1168 -0
  231. package/tempoch-js/tempoch/tempoch-core/src/scales.rs +779 -0
  232. package/tempoch-js/tempoch/tempoch-ffi/Cargo.lock +889 -0
  233. package/tempoch-js/tempoch/tempoch-ffi/Cargo.toml +26 -0
  234. package/tempoch-js/tempoch/tempoch-ffi/build.rs +24 -0
  235. package/tempoch-js/tempoch/tempoch-ffi/cbindgen.toml +30 -0
  236. package/tempoch-js/tempoch/tempoch-ffi/src/error.rs +19 -0
  237. package/tempoch-js/tempoch/tempoch-ffi/src/lib.rs +82 -0
  238. package/tempoch-js/tempoch/tempoch-ffi/src/period.rs +101 -0
  239. package/tempoch-js/tempoch/tempoch-ffi/src/time.rs +711 -0
  240. package/tempoch-js/tempoch/tempoch-ffi/tests/ffi.rs +265 -0
  241. package/tempoch-js/tempoch-node/.prettierignore +6 -0
  242. package/tempoch-js/tempoch-node/.prettierrc.json +6 -0
  243. package/tempoch-js/tempoch-node/Cargo.lock +496 -0
  244. package/tempoch-js/tempoch-node/Cargo.toml +29 -0
  245. package/tempoch-js/tempoch-node/README.md +265 -0
  246. package/tempoch-js/tempoch-node/__test__/index.test.mjs +598 -0
  247. package/tempoch-js/tempoch-node/build.rs +5 -0
  248. package/tempoch-js/tempoch-node/c8.config.json +3 -0
  249. package/tempoch-js/tempoch-node/eslint.config.js +31 -0
  250. package/tempoch-js/tempoch-node/examples/periods.mjs +79 -0
  251. package/tempoch-js/tempoch-node/examples/quickstart.mjs +71 -0
  252. package/tempoch-js/tempoch-node/examples/timescales.mjs +92 -0
  253. package/tempoch-js/tempoch-node/index.d.ts +280 -0
  254. package/tempoch-js/tempoch-node/index.js +32 -0
  255. package/tempoch-js/tempoch-node/lib/JulianDate.js +176 -0
  256. package/tempoch-js/tempoch-node/lib/ModifiedJulianDate.js +156 -0
  257. package/tempoch-js/tempoch-node/lib/Period.js +133 -0
  258. package/tempoch-js/tempoch-node/lib/backend.js +38 -0
  259. package/tempoch-js/tempoch-node/lib/qttyCompat.js +92 -0
  260. package/tempoch-js/tempoch-node/native.cjs +317 -0
  261. package/tempoch-js/tempoch-node/package-lock.json +3223 -0
  262. package/tempoch-js/tempoch-node/package.json +56 -0
  263. package/tempoch-js/tempoch-node/src/lib.rs +573 -0
  264. package/tempoch-js/tempoch-web/Cargo.toml +23 -0
  265. package/tempoch-js/tempoch-web/index.d.ts +95 -0
  266. package/tempoch-js/tempoch-web/index.js +27 -0
  267. package/tempoch-js/tempoch-web/lib/JulianDate.js +170 -0
  268. package/tempoch-js/tempoch-web/lib/ModifiedJulianDate.js +145 -0
  269. package/tempoch-js/tempoch-web/lib/Period.js +121 -0
  270. package/tempoch-js/tempoch-web/lib/backend.js +118 -0
  271. package/tempoch-js/tempoch-web/package.json +46 -0
  272. package/tempoch-js/tempoch-web/src/lib.rs +184 -0
@@ -0,0 +1,9 @@
1
+ # qtty workspace
2
+
3
+ Workspace-level documentation now lives under the repository `doc/` tree.
4
+
5
+ - User overview: [`../doc/users/rust-workspace.md`](../doc/users/rust-workspace.md)
6
+ - Architecture: [`../doc/architecture/repository-layout.md`](../doc/architecture/repository-layout.md)
7
+ - FFI architecture: [`../doc/architecture/qtty-ffi.md`](../doc/architecture/qtty-ffi.md)
8
+
9
+ This file remains only because Cargo metadata expects a workspace README.
@@ -0,0 +1,41 @@
1
+ [package]
2
+ name = "qtty"
3
+ description = "Strongly typed physical and astronomical quantities."
4
+ version.workspace = true
5
+ edition.workspace = true
6
+ authors.workspace = true
7
+ license.workspace = true
8
+ repository.workspace = true
9
+ keywords.workspace = true
10
+ categories.workspace = true
11
+ readme = "README.md"
12
+ documentation = "https://docs.rs/qtty"
13
+
14
+ [features]
15
+ default = ["std", "cross-unit-ops"]
16
+ alloc = []
17
+ std = ["alloc", "qtty-core/std"]
18
+ cross-unit-ops = ["qtty-core/cross-unit-ops"]
19
+ serde = ["qtty-core/serde"]
20
+
21
+ # Scalar type support
22
+ scalar-decimal = ["qtty-core/scalar-decimal"]
23
+ scalar-rational = ["qtty-core/scalar-rational"]
24
+ pyo3 = ["qtty-core/pyo3", "dep:pyo3"]
25
+ tiberius = ["qtty-core/tiberius"]
26
+ diesel = ["qtty-core/diesel"]
27
+
28
+ [dependencies]
29
+ qtty-core = { version = "0.4.0", path = "../qtty-core", default-features = false }
30
+ qtty-derive = { version = "0.4.0", path = "../qtty-derive" }
31
+ pyo3 = { version = "0.28.2", optional = true, features = ["auto-initialize"] }
32
+
33
+ [dev-dependencies]
34
+ approx = "0.5"
35
+ proptest = "1.4"
36
+ serde = { version = "1.0", features = ["derive"] }
37
+ serde_json = "1.0"
38
+
39
+ [[example]]
40
+ name = "python_integration"
41
+ required-features = ["pyo3"]
@@ -0,0 +1,8 @@
1
+ # qtty crate
2
+
3
+ Centralized documentation lives under the repository `doc/` tree.
4
+
5
+ - Workspace overview: [`../../doc/users/rust-workspace.md`](../../doc/users/rust-workspace.md)
6
+ - Repository layout: [`../../doc/architecture/repository-layout.md`](../../doc/architecture/repository-layout.md)
7
+
8
+ This README remains as the crate metadata entrypoint.
@@ -0,0 +1,14 @@
1
+ //! Angle helpers example: wrapping and separation in a single unit type.
2
+
3
+ use qtty::{Arcseconds, Degrees};
4
+
5
+ fn main() {
6
+ let a = Degrees::new(370.0).wrap_signed();
7
+ assert_eq!(a.value(), 10.0);
8
+
9
+ let s = Degrees::new(45.0).abs_separation(Degrees::new(350.0));
10
+ assert_eq!(s.value(), 55.0);
11
+
12
+ let arcsec: Arcseconds = Degrees::new(1.0).to();
13
+ assert_eq!(arcsec.value(), 3600.0);
14
+ }
@@ -0,0 +1,17 @@
1
+ //! Astronomy-flavored example using AU, light-years, and an orbital velocity estimate.
2
+
3
+ use qtty::velocity::Velocity;
4
+ use qtty::{AstronomicalUnits, Days, Kilometer, Kilometers, LightYears, Second, Seconds};
5
+
6
+ fn main() {
7
+ let earth_velocity: Velocity<Kilometer, Second> = Velocity::new(29.78);
8
+ let time = Days::new(1.0);
9
+ let time_sec: Seconds = time.to();
10
+ let distance: Kilometers = (earth_velocity * time_sec).to();
11
+
12
+ assert!((distance.value() - 2_573_395.2).abs() < 5_000.0);
13
+
14
+ let proxima = LightYears::new(4.24);
15
+ let au: AstronomicalUnits = proxima.to();
16
+ assert!(au.value() > 200_000.0);
17
+ }
@@ -0,0 +1,83 @@
1
+ //! Dimensional arithmetic examples.
2
+ //!
3
+ //! Demonstrates how the `*` and `/` operators between quantities automatically
4
+ //! produce the correct dimensional result at compile time.
5
+ //!
6
+ //! Run with:
7
+ //! ```sh
8
+ //! cargo run -p qtty --example dimensional_arithmetic
9
+ //! ```
10
+
11
+ use qtty::area::SquareMeters;
12
+ use qtty::length::{Kilometer, Kilometers, Meter, Meters};
13
+ use qtty::time::{Second, Seconds};
14
+ use qtty::velocity::Velocity;
15
+ use qtty::volume::CubicMeters;
16
+ use qtty::{Per, Quantity, Simplify, Unitless};
17
+
18
+ fn main() {
19
+ // ─────────────────────────────────────────────────────────────────────
20
+ // 1. Length × Length → Area
21
+ // ─────────────────────────────────────────────────────────────────────
22
+ let width = Meters::new(4.0);
23
+ let height = Meters::new(5.0);
24
+
25
+ // The product type is Quantity<Prod<Meter, Meter>>; convert to a named area unit:
26
+ let area: SquareMeters = (width * height).to();
27
+ println!("4 m × 5 m = {} m²", area.value());
28
+ assert!((area.value() - 20.0).abs() < 1e-12);
29
+
30
+ // ─────────────────────────────────────────────────────────────────────
31
+ // 2. Area × Length → Volume
32
+ // ─────────────────────────────────────────────────────────────────────
33
+ let depth = Meters::new(3.0);
34
+ let vol: CubicMeters = (area * depth).to();
35
+ println!("20 m² × 3 m = {} m³", vol.value());
36
+ assert!((vol.value() - 60.0).abs() < 1e-12);
37
+
38
+ // ─────────────────────────────────────────────────────────────────────
39
+ // 3. Length / Time → Velocity
40
+ // ─────────────────────────────────────────────────────────────────────
41
+ let distance = Kilometers::new(100.0);
42
+ let time = Seconds::new(3600.0);
43
+ let speed: Velocity<Kilometer, Second> = distance / time;
44
+ println!("100 km / 3600 s ≈ {:.6} km/s", speed.value());
45
+ assert!((speed.value() - 100.0 / 3600.0).abs() < 1e-12);
46
+
47
+ // ─────────────────────────────────────────────────────────────────────
48
+ // 4. Velocity × Time → recovers Length (via .to())
49
+ // ─────────────────────────────────────────────────────────────────────
50
+ let recovered: Kilometers = (speed * time).to();
51
+ println!(
52
+ "{:.6} km/s × 3600 s = {} km",
53
+ speed.value(),
54
+ recovered.value()
55
+ );
56
+ assert!((recovered.value() - 100.0).abs() < 1e-9);
57
+
58
+ // ─────────────────────────────────────────────────────────────────────
59
+ // 5. Length / Length → dimensionless
60
+ // ─────────────────────────────────────────────────────────────────────
61
+ let a = Meters::new(10.0);
62
+ let b = Meters::new(4.0);
63
+ let ratio: Quantity<Per<Meter, Meter>> = a / b;
64
+ // Simplify to a plain f64 via Unitless:
65
+ let simplified: Quantity<Unitless> = ratio.simplify();
66
+ println!("10 m / 4 m = {} (dimensionless)", simplified.value());
67
+ assert!((simplified.value() - 2.5).abs() < 1e-12);
68
+
69
+ // ─────────────────────────────────────────────────────────────────────
70
+ // 6. Mixed units: km / m keeps the composite type
71
+ // ─────────────────────────────────────────────────────────────────────
72
+ let km = Kilometers::new(1.0);
73
+ let m = Meters::new(500.0);
74
+ let mixed = km / m; // Quantity<Per<Kilometer, Meter>>
75
+ // The value is 1.0/500.0 in "km per m" units:
76
+ println!("1 km / 500 m = {} km/m", mixed.value());
77
+ // But in dimensionless terms (since km/m = 1000) the real ratio is 2.0:
78
+ let pure: Quantity<Unitless> = mixed.to();
79
+ println!(" → as dimensionless = {}", pure.value());
80
+ assert!((pure.value() - 2.0).abs() < 1e-12);
81
+
82
+ println!("\nAll dimensional arithmetic checks passed!");
83
+ }
@@ -0,0 +1,61 @@
1
+ //! Example demonstrating how `Quantity` fields work in `#[pyclass]` structures
2
+ //! when the `qtty-core` crate is built with the `pyo3` feature.
3
+
4
+ #[cfg(feature = "pyo3")]
5
+ use pyo3::prelude::*;
6
+ #[cfg(feature = "pyo3")]
7
+ use qtty::Degrees;
8
+
9
+ #[cfg(feature = "pyo3")]
10
+ #[pyclass]
11
+ pub struct DegreeRange {
12
+ #[pyo3(get, set)]
13
+ pub min: Degrees,
14
+ #[pyo3(get, set)]
15
+ pub max: Degrees,
16
+ }
17
+
18
+ #[cfg(feature = "pyo3")]
19
+ #[pymethods]
20
+ impl DegreeRange {
21
+ #[new]
22
+ fn new(min: f64, max: f64) -> Self {
23
+ Self {
24
+ min: Degrees::new(min),
25
+ max: Degrees::new(max),
26
+ }
27
+ }
28
+
29
+ fn span(&self) -> f64 {
30
+ (self.max - self.min).value()
31
+ }
32
+ }
33
+
34
+ /// A minimal pyo3 module initializer to export `DegreeRange` when building as a Python extension.
35
+ #[cfg(feature = "pyo3")]
36
+ #[pymodule]
37
+ fn qtty_examples(m: &Bound<'_, PyModule>) -> PyResult<()> {
38
+ m.add_class::<DegreeRange>()?;
39
+ Ok(())
40
+ }
41
+
42
+ fn main() {
43
+ #[cfg(feature = "pyo3")]
44
+ {
45
+ Python::attach(|py| {
46
+ let range = DegreeRange::new(0.0, 180.0);
47
+ let obj = Py::new(py, range).expect("create DegreeRange");
48
+ let span: f64 = obj
49
+ .bind(py)
50
+ .call_method0("span")
51
+ .and_then(|v| v.extract())
52
+ .expect("call DegreeRange.span()");
53
+ println!("span = {span}");
54
+ })
55
+ }
56
+
57
+ #[cfg(not(feature = "pyo3"))]
58
+ {
59
+ eprintln!("This example requires `--features pyo3`.");
60
+ }
61
+ }
@@ -0,0 +1,15 @@
1
+ //! Minimal end-to-end example: convert angles and compute a velocity (length / time).
2
+
3
+ use qtty::velocity::Velocity;
4
+ use qtty::{Degrees, Kilometer, Kilometers, Radian, Second, Seconds};
5
+
6
+ fn main() {
7
+ let a = Degrees::new(180.0);
8
+ let r = a.to::<Radian>();
9
+ assert!((r.value() - core::f64::consts::PI).abs() < 1e-12);
10
+
11
+ let d = Kilometers::new(1_000.0);
12
+ let t = Seconds::new(100.0);
13
+ let v: Velocity<Kilometer, Second> = d / t;
14
+ assert!((v.value() - 10.0).abs() < 1e-12);
15
+ }
@@ -0,0 +1,12 @@
1
+ //! Derived-unit example: ratios and `Simplify` to recover `Unitless`.
2
+
3
+ use qtty::{Meters, Seconds, Simplify, Unitless};
4
+
5
+ fn main() {
6
+ let half = Meters::new(1.0) / Meters::new(2.0);
7
+ let unitless: qtty::Quantity<Unitless> = half.simplify();
8
+ assert!((unitless.value() - 0.5).abs() < 1e-12);
9
+
10
+ let ratio = Seconds::new(1.0) / Seconds::new(1.0);
11
+ assert_eq!(ratio.asin(), core::f64::consts::FRAC_PI_2);
12
+ }
@@ -0,0 +1,234 @@
1
+ //! Example demonstrating the serde_with_unit helper module.
2
+ //!
3
+ //! This shows how to use #[serde(with = "qtty_core::serde_with_unit")] to preserve
4
+ //! unit information in serialized data on a per-field basis.
5
+ //!
6
+ //! Run with: cargo run --example serde_with_unit --features serde
7
+
8
+ #[cfg(feature = "serde")]
9
+ fn main() {
10
+ use qtty::{Kilometers, Meters, Seconds};
11
+ use serde::{Deserialize, Serialize};
12
+ use serde_json;
13
+
14
+ println!("=== Using serde_with_unit Helper ===\n");
15
+
16
+ // =========================================================================
17
+ // Example 1: Basic Usage - Mixed Serialization
18
+ // =========================================================================
19
+ println!("1. Basic Usage - Per-Field Control:\n");
20
+
21
+ #[derive(Serialize, Deserialize, Debug)]
22
+ struct SensorData {
23
+ // This field will serialize WITH unit information
24
+ #[serde(with = "qtty_core::serde_with_unit")]
25
+ max_range: Meters,
26
+
27
+ // This field uses default (compact) serialization
28
+ current_distance: Meters,
29
+
30
+ // Another field with unit info
31
+ #[serde(with = "qtty_core::serde_with_unit")]
32
+ timestamp: Seconds,
33
+ }
34
+
35
+ let data = SensorData {
36
+ max_range: Meters::new(100.0),
37
+ current_distance: Meters::new(42.5),
38
+ timestamp: Seconds::new(1702562400.0),
39
+ };
40
+
41
+ let json = serde_json::to_string_pretty(&data).unwrap();
42
+ println!("Serialized:\n{}\n", json);
43
+
44
+ // Deserialize back
45
+ let restored: SensorData = serde_json::from_str(&json).unwrap();
46
+ println!("Deserialized successfully!");
47
+ println!(" max_range: {}", restored.max_range);
48
+ println!(" current_distance: {}", restored.current_distance);
49
+ println!(" timestamp: {}\n", restored.timestamp);
50
+
51
+ // =========================================================================
52
+ // Example 2: External API Response
53
+ // =========================================================================
54
+ println!("2. Self-Documenting API Response:\n");
55
+
56
+ #[derive(Serialize, Deserialize, Debug)]
57
+ struct WeatherReport {
58
+ station_id: String,
59
+
60
+ #[serde(with = "qtty_core::serde_with_unit")]
61
+ temperature_celsius: Meters, // Using Meters as example
62
+
63
+ #[serde(with = "qtty_core::serde_with_unit")]
64
+ wind_speed: Meters,
65
+
66
+ #[serde(with = "qtty_core::serde_with_unit")]
67
+ visibility: Kilometers,
68
+ }
69
+
70
+ let report = WeatherReport {
71
+ station_id: "KJFK".to_string(),
72
+ temperature_celsius: Meters::new(22.0),
73
+ wind_speed: Meters::new(5.5),
74
+ visibility: Kilometers::new(10.0),
75
+ };
76
+
77
+ let json = serde_json::to_string_pretty(&report).unwrap();
78
+ println!("Weather API Response:\n{}\n", json);
79
+
80
+ // =========================================================================
81
+ // Example 3: Configuration File
82
+ // =========================================================================
83
+ println!("3. Configuration File Format:\n");
84
+
85
+ #[derive(Serialize, Deserialize, Debug)]
86
+ struct RobotConfig {
87
+ name: String,
88
+
89
+ // Document the units in config files
90
+ #[serde(with = "qtty_core::serde_with_unit")]
91
+ max_speed: Meters,
92
+
93
+ #[serde(with = "qtty_core::serde_with_unit")]
94
+ safe_distance: Meters,
95
+
96
+ #[serde(with = "qtty_core::serde_with_unit")]
97
+ timeout: Seconds,
98
+
99
+ // Internal value doesn't need unit documentation
100
+ calibration_offset: Meters,
101
+ }
102
+
103
+ let config = RobotConfig {
104
+ name: "R2D2".to_string(),
105
+ max_speed: Meters::new(2.5),
106
+ safe_distance: Meters::new(0.5),
107
+ timeout: Seconds::new(30.0),
108
+ calibration_offset: Meters::new(0.001),
109
+ };
110
+
111
+ let json = serde_json::to_string_pretty(&config).unwrap();
112
+ println!("Robot Configuration:\n{}\n", json);
113
+
114
+ // =========================================================================
115
+ // Example 4: Unit Validation on Deserialization
116
+ // =========================================================================
117
+ println!("4. Unit Validation:\n");
118
+
119
+ // Valid JSON with unit info
120
+ #[derive(Serialize, Deserialize, Debug)]
121
+ struct SingleValue {
122
+ #[serde(with = "qtty_core::serde_with_unit")]
123
+ distance: Meters,
124
+ }
125
+
126
+ let valid_json = r#"{"distance": {"value": 100.0, "unit": "m"}}"#;
127
+ let data: SingleValue =
128
+ serde_json::from_str(valid_json).expect("Should deserialize with matching unit");
129
+ println!("✓ Valid JSON with correct unit: {}", data.distance);
130
+
131
+ // Missing unit field (backwards compatible)
132
+ let no_unit_json = r#"{"distance": {"value": 50.0}}"#;
133
+ let data2: SingleValue =
134
+ serde_json::from_str(no_unit_json).expect("Should work without unit field");
135
+ println!("✓ Valid JSON without unit field: {}", data2.distance);
136
+
137
+ // Wrong unit (will fail validation)
138
+ let invalid_json = r#"{"distance": {"value": 100.0, "unit": "kg"}}"#;
139
+ match serde_json::from_str::<SingleValue>(invalid_json) {
140
+ Ok(_) => println!("✗ Unexpected success with wrong unit"),
141
+ Err(e) => println!("✓ Correctly rejected wrong unit: {}", e),
142
+ }
143
+ println!();
144
+
145
+ // =========================================================================
146
+ // Example 5: Collections with Mixed Serialization
147
+ // =========================================================================
148
+ println!("5. Collections:\n");
149
+
150
+ #[derive(Serialize, Deserialize, Debug)]
151
+ struct Measurement {
152
+ id: u32,
153
+
154
+ #[serde(with = "qtty_core::serde_with_unit")]
155
+ value: Meters,
156
+ }
157
+
158
+ let measurements = vec![
159
+ Measurement {
160
+ id: 1,
161
+ value: Meters::new(10.0),
162
+ },
163
+ Measurement {
164
+ id: 2,
165
+ value: Meters::new(20.0),
166
+ },
167
+ Measurement {
168
+ id: 3,
169
+ value: Meters::new(30.0),
170
+ },
171
+ ];
172
+
173
+ let json = serde_json::to_string_pretty(&measurements).unwrap();
174
+ println!("Measurement Array:\n{}\n", json);
175
+
176
+ // =========================================================================
177
+ // Example 6: Nested Structures
178
+ // =========================================================================
179
+ println!("6. Nested Structures:\n");
180
+
181
+ #[derive(Serialize, Deserialize, Debug)]
182
+ struct Location {
183
+ name: String,
184
+ coordinates: Coordinates,
185
+ }
186
+
187
+ #[derive(Serialize, Deserialize, Debug)]
188
+ struct Coordinates {
189
+ #[serde(with = "qtty_core::serde_with_unit")]
190
+ x: Meters,
191
+
192
+ #[serde(with = "qtty_core::serde_with_unit")]
193
+ y: Meters,
194
+
195
+ #[serde(with = "qtty_core::serde_with_unit")]
196
+ z: Meters,
197
+ }
198
+
199
+ let location = Location {
200
+ name: "Observatory".to_string(),
201
+ coordinates: Coordinates {
202
+ x: Meters::new(100.0),
203
+ y: Meters::new(200.0),
204
+ z: Meters::new(50.0),
205
+ },
206
+ };
207
+
208
+ let json = serde_json::to_string_pretty(&location).unwrap();
209
+ println!("Nested structure:\n{}\n", json);
210
+
211
+ // =========================================================================
212
+ // Summary
213
+ // =========================================================================
214
+ println!("=== Summary ===\n");
215
+ println!("✓ Use #[serde(with = \"qtty_core::serde_with_unit\")] for:");
216
+ println!(" • External/public APIs");
217
+ println!(" • Configuration files");
218
+ println!(" • Self-documenting data");
219
+ println!(" • When consumers might not know the units");
220
+ println!();
221
+ println!("✓ Use default serialization (no attribute) for:");
222
+ println!(" • Internal APIs");
223
+ println!(" • Performance-critical code");
224
+ println!(" • Large datasets");
225
+ println!(" • When types provide sufficient documentation");
226
+ println!();
227
+ println!("✓ Mix both in the same struct as needed!");
228
+ }
229
+
230
+ #[cfg(not(feature = "serde"))]
231
+ fn main() {
232
+ println!("This example requires the 'serde' feature.");
233
+ println!("Run with: cargo run --example serde_with_unit --features serde");
234
+ }
@@ -0,0 +1,141 @@
1
+ //! Examples of serializing and deserializing quantities.
2
+ //!
3
+ //! This example demonstrates how to use serde to serialize and deserialize
4
+ //! physical quantities to/from JSON and other formats.
5
+ //!
6
+ //! To run this example with serde support:
7
+ //! ```bash
8
+ //! cargo run --example serialization --features serde
9
+ //! ```
10
+
11
+ #[cfg(feature = "serde")]
12
+ fn main() {
13
+ use qtty::velocity::Velocity;
14
+ use qtty::{Kilograms, Kilometers, Meter, Meters, Second, Seconds, Watts};
15
+ use serde::{Deserialize, Serialize};
16
+ use serde_json;
17
+
18
+ println!("=== Quantity Serialization Examples ===\n");
19
+
20
+ // Example 1: Basic serialization to JSON
21
+ println!("1. Basic JSON Serialization:");
22
+ let distance = Meters::new(42.5);
23
+ let json = serde_json::to_string(&distance).unwrap();
24
+ println!(" Distance: {} → JSON: {}", distance, json);
25
+
26
+ let time = Seconds::new(std::f64::consts::PI);
27
+ let json = serde_json::to_string(&time).unwrap();
28
+ println!(" Time: {} → JSON: {}", time, json);
29
+
30
+ let mass = Kilograms::new(100.0);
31
+ let json = serde_json::to_string(&mass).unwrap();
32
+ println!(" Mass: {} → JSON: {}", mass, json);
33
+ println!();
34
+
35
+ // Example 2: Deserialization from JSON
36
+ println!("2. JSON Deserialization:");
37
+ let json_distance = "42.5";
38
+ let distance = serde_json::from_str::<Meters>(json_distance).unwrap();
39
+ println!(" JSON: {} → {}", json_distance, distance);
40
+
41
+ let json_time = "3.14";
42
+ let time = serde_json::from_str::<Seconds>(json_time).unwrap();
43
+ println!(" JSON: {} → {}", json_time, time);
44
+ println!();
45
+
46
+ // Example 3: Round-trip serialization
47
+ println!("3. Round-trip Serialization:");
48
+ let original_distance = Meters::new(299792458.0);
49
+ let original_time = Seconds::new(1.0);
50
+ let original: Velocity<Meter, Second> = original_distance / original_time;
51
+ let json = serde_json::to_string(&original).unwrap();
52
+ let restored = serde_json::from_str::<Velocity<Meter, Second>>(&json).unwrap();
53
+ println!(" Original: {}", original);
54
+ println!(" JSON: {}", json);
55
+ println!(" Restored: {}", restored);
56
+ println!(
57
+ " Equal: {}",
58
+ (original.value() - restored.value()).abs() < 1e-6
59
+ );
60
+ println!();
61
+
62
+ // Example 4: Serializing structs containing quantities
63
+ #[derive(Serialize, Deserialize, Debug)]
64
+ struct Measurement {
65
+ distance: Meters,
66
+ time: Seconds,
67
+ mass: Kilograms,
68
+ }
69
+
70
+ println!("4. Serializing Structs with Quantities:");
71
+ let measurement = Measurement {
72
+ distance: Meters::new(100.0),
73
+ time: Seconds::new(9.58),
74
+ mass: Kilograms::new(75.0),
75
+ };
76
+
77
+ let json = serde_json::to_string_pretty(&measurement).unwrap();
78
+ println!(" Struct to JSON:\n{}", json);
79
+
80
+ let restored: Measurement = serde_json::from_str(&json).unwrap();
81
+ println!(" Restored: {:?}", restored);
82
+ println!();
83
+
84
+ // Example 5: Serializing collections of quantities
85
+ println!("5. Serializing Collections:");
86
+ let distances = vec![Meters::new(10.0), Meters::new(20.0), Meters::new(30.0)];
87
+ let json = serde_json::to_string(&distances).unwrap();
88
+ println!(" Vec of distances → JSON: {}", json);
89
+
90
+ let restored: Vec<Meters> = serde_json::from_str(&json).unwrap();
91
+ println!(" Restored: {:?}", restored);
92
+ println!();
93
+
94
+ // Example 6: Using pretty printing
95
+ println!("6. Pretty-printed JSON:");
96
+ #[derive(Serialize, Deserialize)]
97
+ struct Experiment {
98
+ name: String,
99
+ height: Meters,
100
+ duration: Seconds,
101
+ velocity: Velocity<Meter, Second>,
102
+ }
103
+
104
+ let experiment = Experiment {
105
+ name: "Free Fall Test".to_string(),
106
+ height: Meters::new(100.0),
107
+ duration: Seconds::new(4.52),
108
+ velocity: Meters::new(44.3) / Seconds::new(1.0),
109
+ };
110
+
111
+ let json = serde_json::to_string_pretty(&experiment).unwrap();
112
+ println!("{}", json);
113
+ println!();
114
+
115
+ // Example 7: Handling conversion before serialization
116
+ println!("7. Converting Units Before Serialization:");
117
+ let distance_km = Kilometers::new(5.0);
118
+ // Convert to base unit (meter) before serializing
119
+ let distance_m = distance_km.to::<Meter>();
120
+ let json = serde_json::to_string(&distance_m).unwrap();
121
+ println!(" {} → {} → JSON: {}", distance_km, distance_m, json);
122
+ println!();
123
+
124
+ // Example 8: Derived quantities
125
+ println!("8. Serializing Derived Quantities:");
126
+ let power = Watts::new(1500.0);
127
+ let json = serde_json::to_string(&power).unwrap();
128
+ println!(" Power: {} → JSON: {}", power, json);
129
+
130
+ println!("=== Important Notes ===");
131
+ println!("• Quantities serialize as bare f64 values (the numeric value only)");
132
+ println!("• Unit information is NOT preserved in serialization");
133
+ println!("• You must specify the correct unit type when deserializing");
134
+ println!("• Always use the base SI unit for consistency when serializing");
135
+ }
136
+
137
+ #[cfg(not(feature = "serde"))]
138
+ fn main() {
139
+ println!("This example requires the 'serde' feature.");
140
+ println!("Run with: cargo run --example serialization --features serde");
141
+ }