cosmol-viewer 0.1.5.dev6__tar.gz → 0.1.5.dev8__tar.gz

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 (37) hide show
  1. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/Cargo.lock +260 -24
  2. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/Cargo.toml +3 -3
  3. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/PKG-INFO +1 -1
  4. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/core/Cargo.toml +3 -0
  5. cosmol_viewer-0.1.5.dev6/crates/core/src/parser/compute_secondary_structure.rs → cosmol_viewer-0.1.5.dev8/crates/core/src/parser/DSSP.rs +12 -0
  6. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/core/src/parser/mmcif.rs +5 -9
  7. cosmol_viewer-0.1.5.dev8/crates/core/src/parser/mod.rs +3 -0
  8. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/core/src/scene.rs +1 -1
  9. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/core/src/shapes/molecules.rs +4 -4
  10. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/core/src/shapes/protein.rs +3 -1
  11. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/core/src/utils.rs +179 -18
  12. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/python/Cargo.toml +8 -1
  13. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/wasm/Cargo.toml +26 -3
  14. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/wasm/src/lib.rs +45 -15
  15. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/pyproject.toml +1 -1
  16. cosmol_viewer-0.1.5.dev6/crates/core/src/parser/mod.rs +0 -3
  17. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/README.md +0 -0
  18. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/core/src/lib.rs +0 -0
  19. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/core/src/parser/sdf.rs +0 -0
  20. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/core/src/shader/bg_fragment.glsl +0 -0
  21. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/core/src/shader/bg_vertex.glsl +0 -0
  22. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/core/src/shader/canvas.rs +0 -0
  23. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/core/src/shader/fragment.glsl +0 -0
  24. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/core/src/shader/mod.rs +0 -0
  25. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/core/src/shader/vertex.glsl +0 -0
  26. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/core/src/shader/vertex_sphere.glsl +0 -0
  27. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/core/src/shader/vertex_stick.glsl +0 -0
  28. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/core/src/shapes/mod.rs +0 -0
  29. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/core/src/shapes/sphere.rs +0 -0
  30. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/core/src/shapes/stick.rs +0 -0
  31. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/python/README.md +0 -0
  32. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/python/build.rs +0 -0
  33. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/python/cosmol_viewer.pyi +0 -0
  34. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/python/src/lib.rs +0 -0
  35. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/python/src/parser.rs +0 -0
  36. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/python/src/render_molecule.py +0 -0
  37. {cosmol_viewer-0.1.5.dev6 → cosmol_viewer-0.1.5.dev8}/crates/python/src/shapes.rs +0 -0
@@ -222,12 +222,6 @@ dependencies = [
222
222
  "x11rb",
223
223
  ]
224
224
 
225
- [[package]]
226
- name = "arc-swap"
227
- version = "1.7.1"
228
- source = "registry+https://github.com/rust-lang/crates.io-index"
229
- checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
230
-
231
225
  [[package]]
232
226
  name = "arg_enum_proc_macro"
233
227
  version = "0.3.4"
@@ -529,6 +523,12 @@ version = "0.22.1"
529
523
  source = "registry+https://github.com/rust-lang/crates.io-index"
530
524
  checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
531
525
 
526
+ [[package]]
527
+ name = "base64ct"
528
+ version = "1.8.0"
529
+ source = "registry+https://github.com/rust-lang/crates.io-index"
530
+ checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba"
531
+
532
532
  [[package]]
533
533
  name = "bincode"
534
534
  version = "2.0.1"
@@ -753,6 +753,18 @@ dependencies = [
753
753
  "libc",
754
754
  ]
755
755
 
756
+ [[package]]
757
+ name = "chrono"
758
+ version = "0.4.42"
759
+ source = "registry+https://github.com/rust-lang/crates.io-index"
760
+ checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
761
+ dependencies = [
762
+ "iana-time-zone",
763
+ "num-traits",
764
+ "serde",
765
+ "windows-link 0.2.1",
766
+ ]
767
+
756
768
  [[package]]
757
769
  name = "clipboard-win"
758
770
  version = "5.4.1"
@@ -876,15 +888,19 @@ dependencies = [
876
888
 
877
889
  [[package]]
878
890
  name = "cosmol_viewer"
879
- version = "0.1.5-nightly.5"
891
+ version = "0.1.5-nightly.8"
880
892
  dependencies = [
881
893
  "cosmol_viewer_core",
894
+ "serde",
895
+ "serde_json",
882
896
  ]
883
897
 
884
898
  [[package]]
885
899
  name = "cosmol_viewer_core"
886
- version = "0.1.5-nightly.5"
900
+ version = "0.1.5-nightly.8"
887
901
  dependencies = [
902
+ "base64",
903
+ "base64ct",
888
904
  "bytemuck",
889
905
  "eframe",
890
906
  "egui-winit",
@@ -899,6 +915,7 @@ dependencies = [
899
915
  "serde",
900
916
  "serde_json",
901
917
  "serde_repr",
918
+ "serde_with",
902
919
  "wide",
903
920
  ]
904
921
 
@@ -912,17 +929,17 @@ dependencies = [
912
929
  "eframe",
913
930
  "egui_extras",
914
931
  "pyo3",
915
- "pyo3-log",
916
932
  "serde_json",
917
933
  ]
918
934
 
919
935
  [[package]]
920
936
  name = "cosmol_viewer_wasm"
921
- version = "0.1.5-nightly.5"
937
+ version = "0.1.5-nightly.8"
922
938
  dependencies = [
923
939
  "base64",
924
940
  "cosmol_viewer_core",
925
941
  "eframe",
942
+ "flate2",
926
943
  "gloo-timers",
927
944
  "log",
928
945
  "pyo3",
@@ -980,6 +997,51 @@ version = "1.2.0"
980
997
  source = "registry+https://github.com/rust-lang/crates.io-index"
981
998
  checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f"
982
999
 
1000
+ [[package]]
1001
+ name = "darling"
1002
+ version = "0.21.3"
1003
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1004
+ checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0"
1005
+ dependencies = [
1006
+ "darling_core",
1007
+ "darling_macro",
1008
+ ]
1009
+
1010
+ [[package]]
1011
+ name = "darling_core"
1012
+ version = "0.21.3"
1013
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1014
+ checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4"
1015
+ dependencies = [
1016
+ "fnv",
1017
+ "ident_case",
1018
+ "proc-macro2",
1019
+ "quote",
1020
+ "strsim",
1021
+ "syn",
1022
+ ]
1023
+
1024
+ [[package]]
1025
+ name = "darling_macro"
1026
+ version = "0.21.3"
1027
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1028
+ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81"
1029
+ dependencies = [
1030
+ "darling_core",
1031
+ "quote",
1032
+ "syn",
1033
+ ]
1034
+
1035
+ [[package]]
1036
+ name = "deranged"
1037
+ version = "0.5.5"
1038
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1039
+ checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587"
1040
+ dependencies = [
1041
+ "powerfmt",
1042
+ "serde_core",
1043
+ ]
1044
+
983
1045
  [[package]]
984
1046
  name = "dispatch"
985
1047
  version = "0.2.0"
@@ -1049,6 +1111,12 @@ version = "0.1.2"
1049
1111
  source = "registry+https://github.com/rust-lang/crates.io-index"
1050
1112
  checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76"
1051
1113
 
1114
+ [[package]]
1115
+ name = "dyn-clone"
1116
+ version = "1.0.20"
1117
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1118
+ checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555"
1119
+
1052
1120
  [[package]]
1053
1121
  name = "ecolor"
1054
1122
  version = "0.33.2"
@@ -1413,6 +1481,12 @@ dependencies = [
1413
1481
  "miniz_oxide",
1414
1482
  ]
1415
1483
 
1484
+ [[package]]
1485
+ name = "fnv"
1486
+ version = "1.0.7"
1487
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1488
+ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
1489
+
1416
1490
  [[package]]
1417
1491
  name = "foldhash"
1418
1492
  version = "0.1.5"
@@ -1746,6 +1820,12 @@ dependencies = [
1746
1820
  "zerocopy",
1747
1821
  ]
1748
1822
 
1823
+ [[package]]
1824
+ name = "hashbrown"
1825
+ version = "0.12.3"
1826
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1827
+ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
1828
+
1749
1829
  [[package]]
1750
1830
  name = "hashbrown"
1751
1831
  version = "0.15.5"
@@ -1788,6 +1868,30 @@ version = "0.2.1"
1788
1868
  source = "registry+https://github.com/rust-lang/crates.io-index"
1789
1869
  checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
1790
1870
 
1871
+ [[package]]
1872
+ name = "iana-time-zone"
1873
+ version = "0.1.64"
1874
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1875
+ checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb"
1876
+ dependencies = [
1877
+ "android_system_properties",
1878
+ "core-foundation-sys",
1879
+ "iana-time-zone-haiku",
1880
+ "js-sys",
1881
+ "log",
1882
+ "wasm-bindgen",
1883
+ "windows-core 0.61.2",
1884
+ ]
1885
+
1886
+ [[package]]
1887
+ name = "iana-time-zone-haiku"
1888
+ version = "0.1.2"
1889
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1890
+ checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
1891
+ dependencies = [
1892
+ "cc",
1893
+ ]
1894
+
1791
1895
  [[package]]
1792
1896
  name = "icu_collections"
1793
1897
  version = "2.1.1"
@@ -1869,6 +1973,12 @@ dependencies = [
1869
1973
  "zerovec",
1870
1974
  ]
1871
1975
 
1976
+ [[package]]
1977
+ name = "ident_case"
1978
+ version = "1.0.1"
1979
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1980
+ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
1981
+
1872
1982
  [[package]]
1873
1983
  name = "idna"
1874
1984
  version = "1.1.0"
@@ -1930,6 +2040,17 @@ version = "1.12.0"
1930
2040
  source = "registry+https://github.com/rust-lang/crates.io-index"
1931
2041
  checksum = "e7c5cedc30da3a610cac6b4ba17597bdf7152cf974e8aab3afb3d54455e371c8"
1932
2042
 
2043
+ [[package]]
2044
+ name = "indexmap"
2045
+ version = "1.9.3"
2046
+ source = "registry+https://github.com/rust-lang/crates.io-index"
2047
+ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
2048
+ dependencies = [
2049
+ "autocfg",
2050
+ "hashbrown 0.12.3",
2051
+ "serde",
2052
+ ]
2053
+
1933
2054
  [[package]]
1934
2055
  name = "indexmap"
1935
2056
  version = "2.12.1"
@@ -1938,6 +2059,8 @@ checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2"
1938
2059
  dependencies = [
1939
2060
  "equivalent",
1940
2061
  "hashbrown 0.16.1",
2062
+ "serde",
2063
+ "serde_core",
1941
2064
  ]
1942
2065
 
1943
2066
  [[package]]
@@ -2279,7 +2402,7 @@ dependencies = [
2279
2402
  "half",
2280
2403
  "hashbrown 0.16.1",
2281
2404
  "hexf-parse",
2282
- "indexmap",
2405
+ "indexmap 2.12.1",
2283
2406
  "libm",
2284
2407
  "log",
2285
2408
  "num-traits",
@@ -2379,6 +2502,12 @@ dependencies = [
2379
2502
  "num-traits",
2380
2503
  ]
2381
2504
 
2505
+ [[package]]
2506
+ name = "num-conv"
2507
+ version = "0.1.0"
2508
+ source = "registry+https://github.com/rust-lang/crates.io-index"
2509
+ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
2510
+
2382
2511
  [[package]]
2383
2512
  name = "num-derive"
2384
2513
  version = "0.4.2"
@@ -2956,6 +3085,12 @@ dependencies = [
2956
3085
  "zerovec",
2957
3086
  ]
2958
3087
 
3088
+ [[package]]
3089
+ name = "powerfmt"
3090
+ version = "0.2.0"
3091
+ source = "registry+https://github.com/rust-lang/crates.io-index"
3092
+ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
3093
+
2959
3094
  [[package]]
2960
3095
  name = "ppv-lite86"
2961
3096
  version = "0.2.21"
@@ -3053,17 +3188,6 @@ dependencies = [
3053
3188
  "pyo3-build-config",
3054
3189
  ]
3055
3190
 
3056
- [[package]]
3057
- name = "pyo3-log"
3058
- version = "0.13.2"
3059
- source = "registry+https://github.com/rust-lang/crates.io-index"
3060
- checksum = "2f8bae9ad5ba08b0b0ed2bb9c2bdbaeccc69cafca96d78cf0fbcea0d45d122bb"
3061
- dependencies = [
3062
- "arc-swap",
3063
- "log",
3064
- "pyo3",
3065
- ]
3066
-
3067
3191
  [[package]]
3068
3192
  name = "pyo3-macros"
3069
3193
  version = "0.27.1"
@@ -3282,6 +3406,26 @@ dependencies = [
3282
3406
  "bitflags 2.10.0",
3283
3407
  ]
3284
3408
 
3409
+ [[package]]
3410
+ name = "ref-cast"
3411
+ version = "1.0.25"
3412
+ source = "registry+https://github.com/rust-lang/crates.io-index"
3413
+ checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d"
3414
+ dependencies = [
3415
+ "ref-cast-impl",
3416
+ ]
3417
+
3418
+ [[package]]
3419
+ name = "ref-cast-impl"
3420
+ version = "1.0.25"
3421
+ source = "registry+https://github.com/rust-lang/crates.io-index"
3422
+ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da"
3423
+ dependencies = [
3424
+ "proc-macro2",
3425
+ "quote",
3426
+ "syn",
3427
+ ]
3428
+
3285
3429
  [[package]]
3286
3430
  name = "regex"
3287
3431
  version = "1.12.2"
@@ -3391,6 +3535,30 @@ dependencies = [
3391
3535
  "winapi-util",
3392
3536
  ]
3393
3537
 
3538
+ [[package]]
3539
+ name = "schemars"
3540
+ version = "0.9.0"
3541
+ source = "registry+https://github.com/rust-lang/crates.io-index"
3542
+ checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f"
3543
+ dependencies = [
3544
+ "dyn-clone",
3545
+ "ref-cast",
3546
+ "serde",
3547
+ "serde_json",
3548
+ ]
3549
+
3550
+ [[package]]
3551
+ name = "schemars"
3552
+ version = "1.1.0"
3553
+ source = "registry+https://github.com/rust-lang/crates.io-index"
3554
+ checksum = "9558e172d4e8533736ba97870c4b2cd63f84b382a3d6eb063da41b91cce17289"
3555
+ dependencies = [
3556
+ "dyn-clone",
3557
+ "ref-cast",
3558
+ "serde",
3559
+ "serde_json",
3560
+ ]
3561
+
3394
3562
  [[package]]
3395
3563
  name = "scoped-tls"
3396
3564
  version = "1.0.1"
@@ -3470,6 +3638,37 @@ dependencies = [
3470
3638
  "syn",
3471
3639
  ]
3472
3640
 
3641
+ [[package]]
3642
+ name = "serde_with"
3643
+ version = "3.16.1"
3644
+ source = "registry+https://github.com/rust-lang/crates.io-index"
3645
+ checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7"
3646
+ dependencies = [
3647
+ "base64",
3648
+ "chrono",
3649
+ "hex",
3650
+ "indexmap 1.9.3",
3651
+ "indexmap 2.12.1",
3652
+ "schemars 0.9.0",
3653
+ "schemars 1.1.0",
3654
+ "serde_core",
3655
+ "serde_json",
3656
+ "serde_with_macros",
3657
+ "time",
3658
+ ]
3659
+
3660
+ [[package]]
3661
+ name = "serde_with_macros"
3662
+ version = "3.16.1"
3663
+ source = "registry+https://github.com/rust-lang/crates.io-index"
3664
+ checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c"
3665
+ dependencies = [
3666
+ "darling",
3667
+ "proc-macro2",
3668
+ "quote",
3669
+ "syn",
3670
+ ]
3671
+
3473
3672
  [[package]]
3474
3673
  name = "sharded-slab"
3475
3674
  version = "0.1.7"
@@ -3641,6 +3840,12 @@ version = "0.1.1"
3641
3840
  source = "registry+https://github.com/rust-lang/crates.io-index"
3642
3841
  checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
3643
3842
 
3843
+ [[package]]
3844
+ name = "strsim"
3845
+ version = "0.11.1"
3846
+ source = "registry+https://github.com/rust-lang/crates.io-index"
3847
+ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
3848
+
3644
3849
  [[package]]
3645
3850
  name = "syn"
3646
3851
  version = "2.0.111"
@@ -3754,6 +3959,37 @@ dependencies = [
3754
3959
  "zune-jpeg 0.4.21",
3755
3960
  ]
3756
3961
 
3962
+ [[package]]
3963
+ name = "time"
3964
+ version = "0.3.44"
3965
+ source = "registry+https://github.com/rust-lang/crates.io-index"
3966
+ checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d"
3967
+ dependencies = [
3968
+ "deranged",
3969
+ "itoa",
3970
+ "num-conv",
3971
+ "powerfmt",
3972
+ "serde",
3973
+ "time-core",
3974
+ "time-macros",
3975
+ ]
3976
+
3977
+ [[package]]
3978
+ name = "time-core"
3979
+ version = "0.1.6"
3980
+ source = "registry+https://github.com/rust-lang/crates.io-index"
3981
+ checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b"
3982
+
3983
+ [[package]]
3984
+ name = "time-macros"
3985
+ version = "0.2.24"
3986
+ source = "registry+https://github.com/rust-lang/crates.io-index"
3987
+ checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3"
3988
+ dependencies = [
3989
+ "num-conv",
3990
+ "time-core",
3991
+ ]
3992
+
3757
3993
  [[package]]
3758
3994
  name = "tiny-skia"
3759
3995
  version = "0.11.4"
@@ -3804,7 +4040,7 @@ version = "0.23.7"
3804
4040
  source = "registry+https://github.com/rust-lang/crates.io-index"
3805
4041
  checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d"
3806
4042
  dependencies = [
3807
- "indexmap",
4043
+ "indexmap 2.12.1",
3808
4044
  "toml_datetime",
3809
4045
  "toml_parser",
3810
4046
  "winnow",
@@ -4301,7 +4537,7 @@ dependencies = [
4301
4537
  "cfg_aliases",
4302
4538
  "document-features",
4303
4539
  "hashbrown 0.16.1",
4304
- "indexmap",
4540
+ "indexmap 2.12.1",
4305
4541
  "log",
4306
4542
  "naga",
4307
4543
  "once_cell",
@@ -1,6 +1,6 @@
1
1
  [workspace.package]
2
2
  edition = "2024"
3
- version = "0.1.5-nightly.5"
3
+ version = "0.1.5-nightly.8"
4
4
  authors = ["9028 wjt@cosmol.org"]
5
5
  repository = "https://github.com/COSMol-repl/COSMol-viewer"
6
6
  homepage = "https://github.com/COSMol-repl/COSMol-viewer"
@@ -13,8 +13,8 @@ resolver = "2"
13
13
  members = ["crates/python"]
14
14
 
15
15
  [workspace.dependencies]
16
- cosmol_viewer = { version = "0.1.5-nightly.5", path = "cosmol_viewer"}
17
- cosmol_viewer_core = { version = "0.1.5-nightly.5", path = "crates/core" }
16
+ cosmol_viewer = { version = "0.1.5-nightly.8", path = "cosmol_viewer"}
17
+ cosmol_viewer_core = { version = "0.1.5-nightly.8", path = "crates/core" }
18
18
 
19
19
  pyo3 = { version = "0.27.1", features = ["extension-module", "abi3-py37"] }
20
20
  eframe = { version = "0.33.2", features = ["wayland","x11"] }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cosmol-viewer
3
- Version: 0.1.5.dev6
3
+ Version: 0.1.5.dev8
4
4
  Summary: Molecular visualization tools
5
5
  Author-email: 95028 <wjt@cosmol.org>
6
6
  Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
@@ -11,7 +11,9 @@ eframe.workspace = true
11
11
  serde_json.workspace = true
12
12
  egui_extras.workspace = true
13
13
  serde.workspace = true
14
+ base64.workspace = true
14
15
  glam = { version = "0.30.8" , features = ["serde", "bytemuck"] }
16
+ serde_with = { version = "3.16.1", features = ["base64"] }
15
17
  regex = "1.12.2"
16
18
  na_seq = "0.3.6"
17
19
  bytemuck = "1.24.0"
@@ -21,6 +23,7 @@ half = "2.7.1"
21
23
  wide = "0.8.3"
22
24
  kiddo = "5.2.2"
23
25
  image = "0.25.8"
26
+ base64ct = { version = "1.8.0", features = ["alloc"] }
24
27
 
25
28
  [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
26
29
  egui-winit.workspace = true
@@ -1,3 +1,15 @@
1
+ // DSSP secondary structure assignment
2
+ //
3
+ // Ported and adapted from ChimeraX:
4
+ // https://github.com/RBVI/ChimeraX/blob/develop/src/bundles/atomic_lib/atomic_cpp/atomstruct_cpp/CompSS.cpp
5
+ //
6
+ // Original ChimeraX code (c) 2004-2025 Regents of the University of California.
7
+ // Licensed under a BSD-style license; see the original repository for details.
8
+ //
9
+ // Original DSSP algorithm:
10
+ // Kabsch & Sander, Biopolymers 22:2577-2637 (1983)
11
+ // https://doi.org/10.1002/bip.360221211
12
+
1
13
  use crate::parser::mmcif::Residue;
2
14
  use crate::parser::mmcif::SecondaryStructure;
3
15
  use glam::Vec3;
@@ -1,4 +1,4 @@
1
- use crate::parser::compute_secondary_structure::SecondaryStructureCalculator;
1
+ use crate::parser::DSSP::SecondaryStructureCalculator;
2
2
  use crate::utils::vec_f16_scaled;
3
3
  pub use crate::utils::{Logger, RustLogger};
4
4
  use glam::Vec3;
@@ -630,14 +630,10 @@ pub struct Residue {
630
630
  pub sns: usize, // PDB numbering or sequential
631
631
 
632
632
  // Minimum for cartoon backbone
633
- #[serde(with = "vec_f16_scaled")]
634
- pub c: Vec3, // or pseudo-CB for glycine
635
- #[serde(with = "vec_f16_scaled")]
636
- pub n: Vec3, // C-alpha coordinates
637
- #[serde(with = "vec_f16_scaled")]
638
- pub ca: Vec3, // C-alpha coordinates
639
- #[serde(with = "vec_f16_scaled")]
640
- pub o: Vec3, // C-alpha coordinates
633
+ pub c: Vec3, // or pseudo-CB for glycine
634
+ pub n: Vec3, // C-alpha coordinates
635
+ pub ca: Vec3, // C-alpha coordinates
636
+ pub o: Vec3, // C-alpha coordinates
641
637
  pub h: Option<Vec3>, // C-alpha coordinates
642
638
 
643
639
  // Secondary structure tag
@@ -0,0 +1,3 @@
1
+ pub mod DSSP;
2
+ pub mod mmcif;
3
+ pub mod sdf;
@@ -67,7 +67,7 @@ impl InstanceGroups {
67
67
  }
68
68
  }
69
69
 
70
- #[derive(Deserialize, Serialize, Clone)]
70
+ #[derive(Deserialize, Serialize, Debug, Clone)]
71
71
  pub struct Scene {
72
72
  pub background_color: [f32; 3],
73
73
  pub camera_state: CameraState,
@@ -54,11 +54,11 @@ pub enum BondType {
54
54
 
55
55
  #[derive(Serialize, Deserialize, Debug, Clone)]
56
56
  pub struct Molecules {
57
- atom_types: Vec<String>,
57
+ pub atom_types: Vec<String>,
58
58
  #[serde(with = "vec_f16_scaled::vec")]
59
- atoms: Vec<Vec3>,
60
- bond_types: Vec<BondType>,
61
- bonds: Vec<[usize; 2]>,
59
+ pub atoms: Vec<Vec3>,
60
+ pub bond_types: Vec<BondType>,
61
+ pub bonds: Vec<[usize; 2]>,
62
62
  pub quality: u32,
63
63
 
64
64
  pub style: VisualStyle,
@@ -6,13 +6,15 @@ use crate::parser::mmcif::ResidueType;
6
6
  use crate::parser::mmcif::SecondaryStructure;
7
7
  use crate::shapes::protein::ResidueType::AminoAcid;
8
8
  use crate::utils::{MeshData, VisualShape, VisualStyle};
9
+ use crate::utils::{deserialize_bits, serialize_bits};
9
10
  use bytemuck::{Pod, Zeroable};
10
11
  use glam::{Quat, Vec3, Vec4};
11
12
  use na_seq::AtomTypeInRes;
12
13
  use serde::{Deserialize, Serialize};
14
+ use serde_with::{base64::Base64, serde_as};
13
15
  use wide::f32x8;
14
16
 
15
- #[derive(Serialize, Deserialize, Debug, Clone)]
17
+ #[derive(Debug, Clone, Serialize, Deserialize)]
16
18
  pub struct Protein {
17
19
  pub chains: Vec<Chain>,
18
20
  pub center: Vec3,
@@ -200,7 +200,7 @@ pub struct Frames {
200
200
 
201
201
  use half::f16;
202
202
  use serde::{Deserializer, Serializer};
203
- pub mod vec_f16_scaled {
203
+ pub mod vec_f16 {
204
204
  use super::*;
205
205
 
206
206
  pub fn serialize<S, T>(v: &T, s: S) -> Result<S::Ok, S::Error>
@@ -208,11 +208,7 @@ pub mod vec_f16_scaled {
208
208
  S: Serializer,
209
209
  T: IntoF32Slice,
210
210
  {
211
- let bits: Vec<u16> = v
212
- .as_f32_slice()
213
- .iter()
214
- .map(|x| f16::from_f32(*x).to_bits())
215
- .collect();
211
+ let bits: Vec<u32> = v.as_f32_slice().iter().map(|x| x.to_bits()).collect();
216
212
  bits.serialize(s)
217
213
  }
218
214
 
@@ -266,7 +262,7 @@ pub mod vec_f16_scaled {
266
262
  }
267
263
  }
268
264
 
269
- pub mod vec_f16_scaled_scaled {
265
+ pub mod vec_f16_scaled {
270
266
  use super::*;
271
267
 
272
268
  // 你可以选择固定系数,或者运行时传
@@ -303,35 +299,139 @@ pub mod vec_f16_scaled_scaled {
303
299
  pub mod vec {
304
300
  use super::*;
305
301
 
306
- // ---- Vec2 ----
307
- pub fn serialize<S, T>(v: &T, s: S) -> Result<S::Ok, S::Error>
302
+ pub fn serialize<S, T>(v: &Vec<T>, s: S) -> Result<S::Ok, S::Error>
308
303
  where
309
304
  S: Serializer,
310
305
  T: IntoF32Slice,
311
306
  {
312
- let bits: Vec<u16> = v
313
- .as_f32_slice()
307
+ let bits: Vec<Vec<u16>> = v
314
308
  .iter()
315
- .map(|x| f16::from_f32(x * SCALE).to_bits())
309
+ .map(|v| {
310
+ let floats: Vec<f32> = v.as_f32_slice().iter().map(|x| x * SCALE).collect();
311
+ floats
312
+ .into_iter()
313
+ .map(|x| f16::from_f32(x).to_bits())
314
+ .collect()
315
+ })
316
316
  .collect();
317
317
  bits.serialize(s)
318
318
  }
319
319
 
320
- pub fn deserialize<'de, D, T>(d: D) -> Result<T, D::Error>
320
+ pub fn deserialize<'de, D, T>(d: D) -> Result<Vec<T>, D::Error>
321
321
  where
322
322
  D: Deserializer<'de>,
323
323
  T: FromF32Slice,
324
324
  {
325
- let bits: Vec<u16> = Vec::<u16>::deserialize(d)?;
326
- let floats: Vec<f32> = bits
327
- .iter()
328
- .map(|b| f16::from_bits(*b).to_f32() / SCALE)
325
+ let bits: Vec<Vec<u16>> = Vec::<Vec<u16>>::deserialize(d)?;
326
+ let out = bits
327
+ .into_iter()
328
+ .map(|v| {
329
+ let floats: Vec<f32> = v
330
+ .iter()
331
+ .map(|b| f16::from_bits(*b).to_f32() / SCALE)
332
+ .collect();
333
+ T::from_f32_slice(&floats)
334
+ })
329
335
  .collect();
330
- Ok(T::from_f32_slice(&floats))
336
+ Ok(out)
331
337
  }
332
338
  }
333
339
  }
334
340
 
341
+ // pub mod vec_binary {
342
+ // use super::*;
343
+ // use base64::{Engine, engine::general_purpose::STANDARD as b64};
344
+ // use serde::{Deserialize, Deserializer, Serialize, Serializer};
345
+
346
+ // // -------------------------------------------------------
347
+ // // 单个 Vec2 / Vec3:无损(f32 -> u32 bits)
348
+ // // -------------------------------------------------------
349
+ // pub fn serialize<S, T>(v: &T, s: S) -> Result<S::Ok, S::Error>
350
+ // where
351
+ // S: Serializer,
352
+ // T: IntoF32Slice,
353
+ // {
354
+ // let bits: Vec<u32> = v.as_f32_slice().iter().map(|x| x.to_bits()).collect();
355
+ // bits.serialize(s)
356
+ // }
357
+
358
+ // pub fn deserialize<'de, D, T>(d: D) -> Result<T, D::Error>
359
+ // where
360
+ // D: Deserializer<'de>,
361
+ // T: FromF32Slice,
362
+ // {
363
+ // let bits: Vec<u32> = Vec::<u32>::deserialize(d)?;
364
+ // let floats: Vec<f32> = bits.iter().map(|b| f32::from_bits(*b)).collect();
365
+ // Ok(T::from_f32_slice(&floats))
366
+ // }
367
+
368
+ // // ==========================================================
369
+ // // Vec<T>:base64 无损存储(高压缩),不使用 f16
370
+ // // ==========================================================
371
+ // pub mod vec {
372
+ // use super::*;
373
+
374
+ // pub fn serialize<S, T>(v: &Vec<T>, s: S) -> Result<S::Ok, S::Error>
375
+ // where
376
+ // S: Serializer,
377
+ // T: IntoF32Slice,
378
+ // {
379
+ // // 1. flatten 成连续 f32
380
+ // let mut floats = Vec::<f32>::new();
381
+ // for item in v {
382
+ // floats.extend_from_slice(item.as_f32_slice());
383
+ // }
384
+
385
+ // // 2. f32 -> u32 bits -> bytes
386
+ // let mut bytes = Vec::<u8>::new();
387
+ // for f in floats {
388
+ // bytes.extend_from_slice(&f.to_bits().to_le_bytes());
389
+ // }
390
+
391
+ // // 3. base64
392
+ // let encoded = b64.encode(bytes);
393
+
394
+ // s.serialize_str(&encoded)
395
+ // }
396
+
397
+ // pub fn deserialize<'de, D, T>(d: D) -> Result<Vec<T>, D::Error>
398
+ // where
399
+ // D: Deserializer<'de>,
400
+ // T: FromF32Slice,
401
+ // {
402
+ // // 1. base64 decode
403
+ // let encoded = String::deserialize(d)?;
404
+ // let bytes = b64
405
+ // .decode(encoded.as_bytes())
406
+ // .map_err(serde::de::Error::custom)?;
407
+
408
+ // if bytes.len() % 4 != 0 {
409
+ // return Err(serde::de::Error::custom("byte length not aligned"));
410
+ // }
411
+
412
+ // // 2. bytes -> u32 bits -> f32
413
+ // let mut floats = Vec::<f32>::new();
414
+ // for chunk in bytes.chunks_exact(4) {
415
+ // let bits = u32::from_le_bytes(chunk.try_into().unwrap());
416
+ // floats.push(f32::from_bits(bits));
417
+ // }
418
+
419
+ // // 3. 按 T::dim() 重建 T
420
+ // let dim = T::dim();
421
+ // if floats.len() % dim != 0 {
422
+ // return Err(serde::de::Error::custom("dimension mismatch"));
423
+ // }
424
+
425
+ // let mut out = Vec::<T>::new();
426
+ // for chunk in floats.chunks(dim) {
427
+ // out.push(T::from_f32_slice(chunk));
428
+ // }
429
+
430
+ // Ok(out)
431
+ // }
432
+ // }
433
+ // }
434
+
335
435
  // ====== Trait definitions ======
336
436
 
337
437
  pub trait IntoF32Slice {
@@ -380,3 +480,64 @@ impl FromF32Slice for Vec4 {
380
480
  Self::new(v[0], v[1], v[2], v[3])
381
481
  }
382
482
  }
483
+
484
+ use base64::{Engine, engine::general_purpose::STANDARD as B64};
485
+ use bytemuck::Pod;
486
+
487
+ pub mod vec_compact {
488
+ use super::*;
489
+
490
+ pub fn serialize<T, S>(data: &[T], serializer: S) -> Result<S::Ok, S::Error>
491
+ where
492
+ S: Serializer,
493
+ T: Pod,
494
+ {
495
+ if data.is_empty() {
496
+ return serializer.serialize_str("");
497
+ }
498
+
499
+ // 直接 cast 成字节流,最快方式(零拷贝!)
500
+ let bytes = bytemuck::cast_slice(data);
501
+ let encoded = B64.encode(bytes);
502
+ serializer.serialize_str(&encoded)
503
+ }
504
+
505
+ pub fn deserialize<'de, T, D>(deserializer: D) -> Result<Vec<T>, D::Error>
506
+ where
507
+ D: Deserializer<'de>,
508
+ T: Pod,
509
+ {
510
+ let s = String::deserialize(deserializer)?;
511
+ if s.is_empty() {
512
+ return Ok(Vec::new());
513
+ }
514
+
515
+ let bytes = B64.decode(&s).map_err(serde::de::Error::custom)?;
516
+ if bytes.len() % std::mem::size_of::<T>() != 0 {
517
+ return Err(serde::de::Error::custom("length not aligned to type size"));
518
+ }
519
+
520
+ // 安全 + 零拷贝
521
+ Ok(bytemuck::pod_collect_to_vec(&bytes))
522
+ }
523
+ }
524
+
525
+ pub fn serialize_bits<S>(v: &Vec3, serializer: S) -> Result<S::Ok, S::Error>
526
+ where
527
+ S: Serializer,
528
+ {
529
+ let bits: [u32; 3] = [v.x.to_bits(), v.y.to_bits(), v.z.to_bits()];
530
+ bits.serialize(serializer)
531
+ }
532
+
533
+ pub fn deserialize_bits<'de, D>(deserializer: D) -> Result<Vec3, D::Error>
534
+ where
535
+ D: Deserializer<'de>,
536
+ {
537
+ let bits: [u32; 3] = Deserialize::deserialize(deserializer)?;
538
+ Ok(Vec3::new(
539
+ f32::from_bits(bits[0]),
540
+ f32::from_bits(bits[1]),
541
+ f32::from_bits(bits[2]),
542
+ ))
543
+ }
@@ -12,7 +12,6 @@ serde_json.workspace = true
12
12
  base64.workspace = true
13
13
  eframe.workspace = true
14
14
  pyo3.workspace = true
15
- pyo3-log = "0.13.2"
16
15
 
17
16
  [lib]
18
17
  name = "cosmol_viewer"
@@ -22,3 +21,11 @@ crate-type = ["cdylib"]
22
21
  default = []
23
22
  wayland = ["cosmol_viewer_core/wayland"]
24
23
  x11 = ["cosmol_viewer_core/x11"]
24
+
25
+ [profile.release]
26
+ lto = "fat" # 以前叫 "full",现在推荐写 fat
27
+ codegen-units = 1 # 必须和 fat LTO 一起开才有效
28
+ panic = "abort" # 二进制体积暴降,Python 侧反正会接管 panic
29
+ strip = "symbols" # 去掉 debug symbols
30
+ opt-level = "z" # 体积党终极选择,速度损失 <1%
31
+ incremental = false
@@ -18,7 +18,9 @@ web-sys = { version = "0.3.82", features = ["HtmlCanvasElement", "console","Wind
18
18
  wasm-bindgen = { version = "0.2.105", optional = true }
19
19
  gloo-timers = { version = "0.3.0", features = ["futures-core", "futures"], optional = true }
20
20
  pyo3 = { workspace = true, optional = true }
21
- base64 = { workspace = true, optional = true }
21
+ base64 = { workspace = true }
22
+ flate2 = "1.1.5"
23
+
22
24
 
23
25
  [features]
24
26
  default = ["wasm"]
@@ -34,12 +36,33 @@ wasm = [
34
36
 
35
37
  js_bridge = [
36
38
  "pyo3",
37
- "base64",
38
39
  "uuid",
39
40
  ]
40
41
 
41
42
  [lib]
42
43
  crate-type = ["rlib", "cdylib"]
43
44
 
45
+ [package.metadata.wasm-pack.profile.dev]
46
+ wasm-opt = false
47
+
48
+ [package.metadata.wasm-pack.profile.dev.wasm-bindgen]
49
+ debug-js-glue = true
50
+ demangle-name-section = true
51
+ dwarf-debug-info = true
52
+
44
53
  [package.metadata.wasm-pack.profile.release]
45
- # wasm-opt = false
54
+ wasm-opt = [
55
+ "-O4",
56
+ "--enable-simd",
57
+ "--enable-bulk-memory",
58
+ "--enable-mutable-globals",
59
+ "--zero-filled-memory",
60
+ "--strip-producers",
61
+ "--vacuum",
62
+ ]
63
+
64
+ [package.metadata.wasm-pack.profile.release.wasm-bindgen]
65
+ debug-js-glue = false
66
+ demangle-name-section = false
67
+ dwarf-debug-info = false
68
+ split-linked-modules = true
@@ -1,14 +1,16 @@
1
+ use base64::Engine;
1
2
  #[cfg(feature = "wasm")]
2
3
  use cosmol_viewer_core::App;
3
4
  use cosmol_viewer_core::scene::Scene;
4
5
  use cosmol_viewer_core::utils::Logger;
5
6
  #[cfg(feature = "js_bridge")]
6
7
  use serde::Serialize;
8
+ use std::io::Write;
7
9
  use std::sync::Arc;
8
10
  use std::sync::Mutex;
9
11
 
10
12
  #[cfg(not(target_arch = "wasm32"))]
11
- const VERSION: &str = env!("CARGO_PKG_VERSION"); // crate 当前版本号
13
+ const VERSION: &str = env!("CARGO_PKG_VERSION");
12
14
 
13
15
  #[cfg(feature = "wasm")]
14
16
  use web_sys::HtmlCanvasElement;
@@ -91,8 +93,7 @@ impl WasmViewer {
91
93
  height = height
92
94
  );
93
95
 
94
- let scene_json = serde_json::to_string(scene).unwrap();
95
- let escaped = serde_json::to_string(&scene_json).unwrap();
96
+ let escaped = serde_json::to_string(&compress_json(&scene)).unwrap();
96
97
 
97
98
  let combined_js = format!(
98
99
  r#"
@@ -167,14 +168,13 @@ impl WasmViewer {
167
168
  height = height
168
169
  );
169
170
 
170
- let frames_json = serde_json::to_string(&Frames {
171
+ let frames = &Frames {
171
172
  frames,
172
173
  interval,
173
174
  loops,
174
175
  smooth,
175
- })
176
- .unwrap();
177
- let escaped = serde_json::to_string(&frames_json).unwrap();
176
+ };
177
+ let escaped = serde_json::to_string(&compress_json(&frames)).unwrap();
178
178
 
179
179
  let combined_js = format!(
180
180
  r#"
@@ -228,8 +228,7 @@ impl WasmViewer {
228
228
  pub fn call<T: Serialize>(&self, py: Python, name: &str, input: T) -> () {
229
229
  use pyo3::types::PyAnyMethods;
230
230
 
231
- let input_json = serde_json::to_string(&input).unwrap();
232
- let escaped = serde_json::to_string(&input_json).unwrap();
231
+ let escaped = serde_json::to_string(&compress_json(&input)).unwrap();
233
232
  let combined_js = format!(
234
233
  r#"
235
234
  (async function() {{
@@ -345,8 +344,13 @@ impl WebHandle {
345
344
  _canvas: HtmlCanvasElement,
346
345
  scene_json: String,
347
346
  ) -> Result<(), JsValue> {
348
- let _scene: Scene = serde_json::from_str(&scene_json)
349
- .map_err(|e| JsValue::from_str(&format!("Scene parse error: {}", e)))?;
347
+ // let _scene: Scene = serde_json::from_str(&scene_json)
348
+ // .map_err(|e| JsValue::from_str(&format!("Scene parse error: {}", e)))?;
349
+
350
+ let _scene: Scene =
351
+ decompress_json(&scene_json).map_err(|e| JsValue::from_str(&e.to_string()))?;
352
+
353
+ println!("{:?}", _scene);
350
354
 
351
355
  #[cfg(target_arch = "wasm32")]
352
356
  {
@@ -375,8 +379,8 @@ impl WebHandle {
375
379
 
376
380
  #[wasm_bindgen]
377
381
  pub async fn update_scene(&mut self, scene_json: String) -> Result<(), JsValue> {
378
- let scene: Scene = serde_json::from_str(&scene_json)
379
- .map_err(|e| JsValue::from_str(&format!("Scene parse error: {}", e)))?;
382
+ let scene: Scene =
383
+ decompress_json(&scene_json).map_err(|e| JsValue::from_str(&e.to_string()))?;
380
384
 
381
385
  let mut app_guard = self.app.lock().unwrap();
382
386
  if let Some(app) = &mut *app_guard {
@@ -399,8 +403,8 @@ impl WebHandle {
399
403
  {
400
404
  use cosmol_viewer_core::utils::Frames;
401
405
 
402
- let frames: Frames = serde_json::from_str(&_frames_json)
403
- .map_err(|e| JsValue::from_str(&format!("Frames parse error: {}", e)))?;
406
+ let frames: Frames =
407
+ decompress_json(&_frames_json).map_err(|e| JsValue::from_str(&e.to_string()))?;
404
408
 
405
409
  let app = Arc::clone(&self.app);
406
410
  let _ = self
@@ -426,3 +430,29 @@ impl WebHandle {
426
430
  Some("The returned value is omitted!".to_string())
427
431
  }
428
432
  }
433
+
434
+ use base64::engine::general_purpose::STANDARD as B64;
435
+ use flate2::{Compression, read::GzDecoder, write::GzEncoder};
436
+ use serde::ser::Error;
437
+ use std::io::Read;
438
+ /// 把 JSON 压缩成 base64 字符串(用于发送)
439
+ pub fn compress_json<T: serde::Serialize>(value: &T) -> String {
440
+ let json = serde_json::to_string(value).unwrap();
441
+ let mut e = GzEncoder::new(Vec::new(), Compression::best());
442
+ e.write_all(json.as_bytes()).unwrap();
443
+ B64.encode(e.finish().unwrap())
444
+ }
445
+
446
+ // 把 base64 字符串解压成目标类型(用于接收)
447
+ pub fn decompress_json<T: for<'de> serde::Deserialize<'de>>(
448
+ s: &str,
449
+ ) -> Result<T, serde_json::Error> {
450
+ let bytes = B64
451
+ .decode(s)
452
+ .map_err(|_| serde_json::Error::custom("base64 error"))?;
453
+ let mut d = GzDecoder::new(&bytes[..]);
454
+ let mut json = String::new();
455
+ d.read_to_string(&mut json)
456
+ .map_err(|_| serde_json::Error::custom("gzip error"))?;
457
+ serde_json::from_str(&json)
458
+ }
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "cosmol-viewer"
3
- version = "0.1.5.dev6"
3
+ version = "0.1.5.dev8"
4
4
  description = "Molecular visualization tools"
5
5
  authors = [{name = "95028", email = "wjt@cosmol.org"}]
6
6
  readme = "README.md"
@@ -1,3 +0,0 @@
1
- pub mod compute_secondary_structure;
2
- pub mod mmcif;
3
- pub mod sdf;