railway-provider-search-ch-0.1.1/.cargo_vcs_info.json0000644000000001700000000000100161640ustar { "git": { "sha1": "1a043a26eb2d4b0d042d3101a00745fe08ffff5a" }, "path_in_vcs": "railway-provider-search-ch" }railway-provider-search-ch-0.1.1/Cargo.lock0000644000000662470000000000100141600ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 4 [[package]] name = "addr2line" version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] name = "adler2" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "aho-corasick" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "android-tzdata" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" [[package]] name = "android_system_properties" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ "libc", ] [[package]] name = "anstream" version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ "windows-sys", ] [[package]] name = "anstyle-wincon" version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", "once_cell", "windows-sys", ] [[package]] name = "approx" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" dependencies = [ "num-traits", ] [[package]] name = "async-trait" version = "0.1.85" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "autocfg" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", "windows-targets", ] [[package]] name = "bumpalo" version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "cc" version = "1.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229" dependencies = [ "shlex", ] [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", "windows-targets", ] [[package]] name = "chrono-tz" version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d59ae0466b83e838b81a54256c39d5d7c20b9d7daa10510a242d9b75abd5936e" dependencies = [ "chrono", "chrono-tz-build", "phf", ] [[package]] name = "chrono-tz-build" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "433e39f13c9a060046954e0592a8d0a4bcb1040125cbf91cb8ee58964cfb350f" dependencies = [ "parse-zoneinfo", "phf", "phf_codegen", ] [[package]] name = "colorchoice" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "core-foundation-sys" version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "displaydoc" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "env_filter" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" dependencies = [ "log", "regex", ] [[package]] name = "env_logger" version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" dependencies = [ "anstream", "anstyle", "env_filter", "humantime", "log", ] [[package]] name = "form_urlencoded" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] [[package]] name = "geo-types" version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bd1157f0f936bf0cd68dec91e8f7c311afe60295574d62b70d4861a1bfdf2d9" dependencies = [ "approx", "num-traits", "serde", ] [[package]] name = "geojson" version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5d728c1df1fbf328d74151efe6cb0586f79ee813346ea981add69bd22c9241b" dependencies = [ "geo-types", "log", "serde", "serde_json", "thiserror", ] [[package]] name = "gimli" version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "humantime" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "iana-time-zone" version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", "windows-core", ] [[package]] name = "iana-time-zone-haiku" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ "cc", ] [[package]] name = "icu_collections" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" dependencies = [ "displaydoc", "yoke", "zerofrom", "zerovec", ] [[package]] name = "icu_locid" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" dependencies = [ "displaydoc", "litemap", "tinystr", "writeable", "zerovec", ] [[package]] name = "icu_locid_transform" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" dependencies = [ "displaydoc", "icu_locid", "icu_locid_transform_data", "icu_provider", "tinystr", "zerovec", ] [[package]] name = "icu_locid_transform_data" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" [[package]] name = "icu_normalizer" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" dependencies = [ "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", "icu_provider", "smallvec", "utf16_iter", "utf8_iter", "write16", "zerovec", ] [[package]] name = "icu_normalizer_data" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" [[package]] name = "icu_properties" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" dependencies = [ "displaydoc", "icu_collections", "icu_locid_transform", "icu_properties_data", "icu_provider", "tinystr", "zerovec", ] [[package]] name = "icu_properties_data" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" [[package]] name = "icu_provider" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" dependencies = [ "displaydoc", "icu_locid", "icu_provider_macros", "stable_deref_trait", "tinystr", "writeable", "yoke", "zerofrom", "zerovec", ] [[package]] name = "icu_provider_macros" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "idna" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ "idna_adapter", "smallvec", "utf8_iter", ] [[package]] name = "idna_adapter" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" dependencies = [ "icu_normalizer", "icu_properties", ] [[package]] name = "is_terminal_polyfill" version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itoa" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "js-sys" version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ "once_cell", "wasm-bindgen", ] [[package]] name = "libc" version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libm" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "litemap" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "log" version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miniz_oxide" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" dependencies = [ "adler2", ] [[package]] name = "num-traits" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", ] [[package]] name = "object" version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] [[package]] name = "once_cell" version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "parse-zoneinfo" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24" dependencies = [ "regex", ] [[package]] name = "percent-encoding" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "phf" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ "phf_shared", ] [[package]] name = "phf_codegen" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" dependencies = [ "phf_generator", "phf_shared", ] [[package]] name = "phf_generator" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", "rand", ] [[package]] name = "phf_shared" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ "siphasher", ] [[package]] name = "pin-project-lite" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "proc-macro2" version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] [[package]] name = "railway-core" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d7deb97a8ba891afa87df371e3ff33cc541d914d36690f271d28117bc199a12" dependencies = [ "async-trait", "chrono", "chrono-tz", "geojson", "log", "url", ] [[package]] name = "railway-provider-search-ch" version = "0.1.1" dependencies = [ "async-trait", "chrono", "chrono-tz", "env_logger", "railway-core", "serde", "serde_json", "tokio", "url", ] [[package]] name = "rand" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "rand_core", ] [[package]] name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" [[package]] name = "regex" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rustc-demangle" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustversion" version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" [[package]] name = "ryu" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "serde" version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_json" version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "930cfb6e6abf99298aaad7d29abbef7a9999a9a8806a40088f55f0dcec03146b" dependencies = [ "itoa", "memchr", "ryu", "serde", ] [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "siphasher" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "smallvec" version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "stable_deref_trait" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "syn" version = "2.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "synstructure" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "thiserror" version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "tinystr" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ "displaydoc", "zerovec", ] [[package]] name = "tokio" version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ "backtrace", "pin-project-lite", "tokio-macros", ] [[package]] name = "tokio-macros" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "unicode-ident" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "url" version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] [[package]] name = "utf16_iter" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" [[package]] name = "utf8_iter" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "utf8parse" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "wasm-bindgen" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", "proc-macro2", "quote", "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" dependencies = [ "unicode-ident", ] [[package]] name = "windows-core" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ "windows-targets", ] [[package]] name = "windows-sys" version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "write16" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" [[package]] name = "writeable" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" [[package]] name = "yoke" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" dependencies = [ "serde", "stable_deref_trait", "yoke-derive", "zerofrom", ] [[package]] name = "yoke-derive" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", "syn", "synstructure", ] [[package]] name = "zerofrom" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", "syn", "synstructure", ] [[package]] name = "zerovec" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" dependencies = [ "yoke", "zerofrom", "zerovec-derive", ] [[package]] name = "zerovec-derive" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", "syn", ] railway-provider-search-ch-0.1.1/Cargo.toml0000644000000031260000000000100141660ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "railway-provider-search-ch" version = "0.1.1" authors = ["Julian Schmidhuber "] build = false autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "Implementation of the search.ch client for Railway" readme = "README.md" keywords = [ "railway-backend", "train", "public-transport", ] license = "AGPL-3.0-or-later OR EUPL-1.2" repository = "https://gitlab.com/schmiddi-on-mobile/railway-backend" [lib] name = "railway_provider_search_ch" path = "src/lib.rs" [dependencies.async-trait] version = "0.1" [dependencies.chrono] version = "0.4" [dependencies.chrono-tz] version = "0.8.6" [dependencies.rcore] version = "0.1" package = "railway-core" [dependencies.serde] version = "1.0" features = ["derive"] [dependencies.serde_json] version = "1.0" [dependencies.url] version = "2.5.0" [dev-dependencies.env_logger] version = "0.11.3" [dev-dependencies.tokio] version = "1.37" features = [ "rt-multi-thread", "macros", ] [features] polylines = ["rcore/polylines"] rt-multi-thread = ["rcore/rt-multi-thread"] railway-provider-search-ch-0.1.1/Cargo.toml.orig000064400000000000000000000020241046102023000176430ustar 00000000000000[package] name = "railway-provider-search-ch" version = "0.1.1" authors = ["Julian Schmidhuber "] edition = "2021" description = "Implementation of the search.ch client for Railway" repository = "https://gitlab.com/schmiddi-on-mobile/railway-backend" license = "AGPL-3.0-or-later OR EUPL-1.2" keywords = ["railway-backend", "train", "public-transport"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] rcore = { package = "railway-core", path = "../railway-core", version = "0.1" } serde = { version = "1.0", features = [ "derive" ] } serde_json = "1.0" chrono = { version = "0.4" } chrono-tz = "0.8.6" url = "2.5.0" async-trait = "0.1" [features] rt-multi-thread = [ "rcore/rt-multi-thread" ] polylines = [ "rcore/polylines" ] [dev-dependencies] tokio = { version = "1.37", features = [ "rt-multi-thread", "macros" ] } env_logger = "0.11.3" rcore = { package = "railway-core", path = "../railway-core", features = [ "reqwest-requester" ] } railway-provider-search-ch-0.1.1/README.md000064400000000000000000000006271046102023000162420ustar 00000000000000# Railway search.ch Provider Implementation of the search.ch client for Railway. This crate is part of [railway-backend](https://gitlab.com/schmiddi-on-mobile/railway-backend). You can find a high-level documentation of railway-backend [here](https://gitlab.com/schmiddi-on-mobile/railway-backend/-/tree/main/docs?ref_type=heads). Documentation can be found [here](https://search.ch/timetable/api/help). railway-provider-search-ch-0.1.1/src/error.rs000064400000000000000000000007011046102023000172420ustar 00000000000000use std::fmt::Display; #[derive(Debug)] pub enum Error { Json(serde_json::Error), RefreshJourneyNotFound, } impl Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { match &self { Self::Json(e) => write!(f, "json error: {}", e), Self::RefreshJourneyNotFound => write!(f, "refresh journey not found"), } } } impl std::error::Error for Error {} railway-provider-search-ch-0.1.1/src/lib.rs000064400000000000000000000214721046102023000166670ustar 00000000000000#![doc = include_str!("../README.md")] mod error; mod serialize; mod types; use error::Error; use types::*; use async_trait::async_trait; use rcore::{ Journey, JourneysOptions, Location, Mode, ProductsSelection, Provider, Requester, RequesterBuilder, }; use url::Url; use std::collections::{HashMap, HashSet}; pub const API_URL: &str = "https://search.ch/timetable/api"; #[derive(Clone)] pub struct SearchChClient { requester: R, url: Url, } impl SearchChClient { pub fn new>(requester: RB) -> Self { Self { requester: requester.build(), url: Url::parse(API_URL).expect("Failed to parse API_URL"), } } } fn products_to_api_type(selection: ProductsSelection) -> String { HashSet::::from(selection) .into_iter() .flat_map(mode_to_api_type) .fold(String::new(), |acc, m| format!("{},{}", acc, m)) } fn mode_to_api_type(mode: Mode) -> Option<&'static str> { match mode { Mode::HighSpeedTrain => Some("train"), Mode::RegionalTrain => Some("train"), Mode::SuburbanTrain => Some("train"), Mode::Subway => Some("tram"), Mode::Tram => Some("tram"), Mode::Bus => Some("bus"), Mode::Ferry => Some("ship"), Mode::Cablecar => Some("cableway"), Mode::OnDemand => None, Mode::Unknown => None, } } #[cfg_attr(feature = "rt-multi-thread", async_trait)] #[cfg_attr(not(feature = "rt-multi-thread"), async_trait(?Send))] impl Provider for SearchChClient { type Error = Error; async fn journeys( &self, from: rcore::Place, to: rcore::Place, opts: rcore::JourneysOptions, ) -> Result::Error, Self::Error>> { let place_to_id = |p| match p { rcore::Place::Station(s) => s.id, rcore::Place::Location(Location::Address { address, .. }) => address, // TODO: Error when not set rcore::Place::Location(Location::Point { id, name, .. }) => { id.or(name).unwrap_or_default() } }; let time = opts .earlier_than .as_ref() .and_then(|t| chrono::DateTime::parse_from_rfc3339(t).ok()) .or_else(|| { opts.later_than .as_ref() .and_then(|t| chrono::DateTime::parse_from_rfc3339(t).ok()) }) .or_else(|| opts.departure.as_ref().map(|t| t.fixed_offset())) .or_else(|| opts.arrival.as_ref().map(|t| t.fixed_offset())) .map(|t| t.with_timezone(&chrono_tz::Europe::Zurich)); let time_type = if opts.arrival.is_some() { "arrival" } else { "depart" }; let num = if opts.earlier_than.is_some() { 0 } else { opts.results }; let pre = if opts.earlier_than.is_some() { opts.results } else { 0 }; let transport_types = products_to_api_type(opts.products); let mut url = self.url.clone(); url.path_segments_mut() .expect("API URL cannot-be-a-base") .push("route.json"); url.query_pairs_mut() .append_pair("from", &place_to_id(from)) .append_pair("to", &place_to_id(to)) .append_pair("show_delays", "1") .append_pair("show_trackchanges", "1") .append_pair( "date", &time .as_ref() .map(|t| t.format("%d.%m.%Y").to_string()) .unwrap_or_else(|| "today".to_owned()), ) .append_pair( "time", &time .as_ref() .map(|t| t.format("%H:%M").to_string()) .unwrap_or_else(|| "now".to_owned()), ) .append_pair("time_type", time_type) .append_pair("num", &num.to_string()) .append_pair("pre", &pre.to_string()) .append_pair("transportation_types", &transport_types); let response = self .requester .get(&url, &[], HashMap::new()) .await .map_err(rcore::Error::Request)?; let response: SearchChJourneysResponse = serde_json::from_slice(&response) .map_err(|e| rcore::Error::Provider(Error::Json(e)))?; Ok(response.into()) } /// Note: search.ch does not support setting the search language or the number of results async fn locations( &self, opts: rcore::LocationsOptions, ) -> Result::Error, Self::Error>> { let mut url = self.url.clone(); url.path_segments_mut() .expect("API URL cannot-be-a-base") .push("completion.json"); url.query_pairs_mut() .append_pair("term", &opts.query) .append_pair("show_ids", "1") .append_pair("show_coordinates", "1"); let response = self .requester .get(&url, &[], HashMap::new()) .await .map_err(rcore::Error::Request)?; let response: SearchChLocationsResponse = serde_json::from_slice(&response) .map_err(|e| rcore::Error::Provider(Error::Json(e)))?; Ok(response.into_iter().map(Into::into).collect()) } // Note: search.ch does not support any of those options. // This method is not guaranteed to find the same journey. But I think this is the best we can do as search.ch does not provide a refresh-API. async fn refresh_journey( &self, journey: &Journey, _opts: rcore::RefreshJourneyOptions, ) -> Result::Error, Self::Error>> { // Note: Each journey should have at least one leg. let from = &journey.legs[0].origin; let to = &journey.legs[journey.legs.len() - 1].destination; let jopts = JourneysOptions { // In most cases, the journey to refresh is likely the first one. Relax this requirement a bit. results: 3, departure: journey.legs[0].planned_departure, ..Default::default() }; self.journeys(from.clone(), to.clone(), jopts) .await? .journeys .into_iter() .find(|j| j.id == journey.id) .clone() .ok_or(rcore::Error::Provider(Error::RefreshJourneyNotFound)) } } #[cfg(test)] mod test { use rcore::{ JourneysOptions, Location, LocationsOptions, Place, ReqwestRequesterBuilder, Station, }; use super::*; pub async fn check_search>( search: S, expected: S, ) -> Result<(), Box> { let client = SearchChClient::new(ReqwestRequesterBuilder::default()); let locations = client .locations(LocationsOptions { query: search.as_ref().to_string(), ..Default::default() }) .await?; let results = locations .into_iter() .flat_map(|p| match p { Place::Station(s) => s.name, Place::Location(Location::Address { address, .. }) => Some(address), Place::Location(Location::Point { name, .. }) => name, }) .collect::>(); assert!( results.iter().find(|s| s == &expected.as_ref()).is_some(), "expected {} to be contained in {:#?}", expected.as_ref(), results ); Ok(()) } pub async fn check_journey>( from: S, to: S, ) -> Result<(), Box> { let client = SearchChClient::new(ReqwestRequesterBuilder::default()); let journeys = client .journeys( Place::Station(Station { id: from.as_ref().to_string(), ..Default::default() }), Place::Station(Station { id: to.as_ref().to_string(), ..Default::default() }), JourneysOptions::default(), ) .await?; assert!( !journeys.journeys.is_empty(), "expected journey from {} to {} to exist", from.as_ref(), to.as_ref() ); Ok(()) } #[tokio::test] async fn search_luzern() -> Result<(), Box> { check_search("Lu", "Luzern").await } #[tokio::test] async fn journey_winterthur_lausanne() -> Result<(), Box> { check_journey("8506000", "8501120").await } } railway-provider-search-ch-0.1.1/src/serialize.rs000064400000000000000000000032021046102023000200770ustar 00000000000000// From . pub(crate) mod time { use chrono::NaiveDateTime; use serde::{self, Deserialize, Deserializer, Serializer}; const FORMAT: &str = "%Y-%m-%d %H:%M:%S"; pub fn serialize(date: &NaiveDateTime, serializer: S) -> Result where S: Serializer, { let s = format!("{}", date.format(FORMAT)); serializer.serialize_str(&s) } pub fn deserialize<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, { let s = String::deserialize(deserializer)?; let dt = NaiveDateTime::parse_from_str(&s, FORMAT).map_err(serde::de::Error::custom)?; Ok(dt) } } pub(crate) mod optional_time { use chrono::NaiveDateTime; use serde::{self, Deserialize, Deserializer, Serializer}; const FORMAT: &str = "%Y-%m-%d %H:%M:%S"; pub fn serialize(date: &Option, serializer: S) -> Result where S: Serializer, { if let Some(date) = date { let s = format!("{}", date.format(FORMAT)); serializer.serialize_str(&s) } else { serializer.serialize_none() } } pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { let s: Option = Option::deserialize(deserializer)?; if let Some(s) = s { let dt = NaiveDateTime::parse_from_str(&s, FORMAT).map_err(serde::de::Error::custom)?; Ok(Some(dt)) } else { Ok(None) } } } railway-provider-search-ch-0.1.1/src/types.rs000064400000000000000000000361251046102023000172660ustar 00000000000000use crate::serialize; use rcore::{ IntermediateLocation, Journey, JourneysResponse, Leg, Line, Location, Mode, Operator, Place, Product, Remark, Station, Stop, }; use chrono::{DateTime, Duration, NaiveDateTime}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; fn convert_datetime(t: NaiveDateTime) -> Option> { // Note: Should in theory never return `None` as the returned time is in Europe/Zurich time. // This time could be ambiguous though (when switching between summer/winter time), not sure what we can do there as the API does not specify which is the correct one. t.and_local_timezone(chrono_tz::Europe::Zurich).earliest() } fn convert_datetime_with_delay>( t: NaiveDateTime, d: Option, ) -> Option> { let time = convert_datetime(t)?; if let Some(d) = d { let d = d.as_ref(); let delay = d .parse::() .map(Duration::minutes) .unwrap_or_else(|_| Duration::zero()); Some(time + delay) } else { Some(time) } } fn type_string_to_mode>(s: S) -> Mode { match s.as_ref() { "strain" => Mode::SuburbanTrain, "walk" => Mode::Unknown, "tram" => Mode::Tram, "express_train" => Mode::HighSpeedTrain, "bus" => Mode::Bus, // TODO _ => Mode::Unknown, } } pub type SearchChLocationsResponse = Vec; #[derive(Serialize, Deserialize, Debug, Clone)] pub struct SearchChLocationsResponseItem { label: String, id: Option, lon: Option, lat: Option, } impl From for Place { fn from(item: SearchChLocationsResponseItem) -> Place { if let Some(id) = item.id { Place::Station(Station { id: id.clone(), name: Some(item.label.clone()), location: Some(Location::Point { id: Some(id), name: Some(item.label), poi: None, latitude: item.lat.unwrap_or_default(), longitude: item.lon.unwrap_or_default(), }), products: vec![], }) } else { // Lat/Lon not given. Place::Location(Location::Address { address: item.label, latitude: item.lat.unwrap_or_default(), longitude: item.lon.unwrap_or_default(), }) } } } #[derive(Serialize, Deserialize, Debug, Clone)] pub struct SearchChJourneysResponse { connections: Vec, } #[derive(Serialize, Deserialize, Debug, Clone)] pub struct SearchChConnection { from: String, #[serde(with = "serialize::time")] departure: chrono::NaiveDateTime, dep_delay: Option, to: String, #[serde(with = "serialize::time")] arrival: chrono::NaiveDateTime, arr_delay: Option, // Note: Sometimes int, sometimes float duration: f64, // is_main, disruptions legs: Vec, } #[derive(Serialize, Deserialize, Debug, Clone)] pub struct SearchChLeg { #[serde(default)] #[serde(with = "serialize::optional_time")] departure: Option, tripid: Option, stopid: String, // x, y name: String, // sbb_name, line, terminal, fgcolor, bgcolor r#type: Option, #[serde(rename = "*G")] star_g: Option, #[serde(rename = "*L")] star_l: Option, operator: Option, stops: Option>, // contop_stop, runningtime exit: Option, // occupancy dep_delay: Option, track: Option, type_name: Option, lon: f32, lat: f32, cancelled: Option, // Note: This either is a map or an empty vec. disruptions: Option, // TODO: Attributes } #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(untagged)] pub enum SearchChDisruptions { Map(HashMap), Vec(Vec), } impl From for Vec { fn from(disruptions: SearchChDisruptions) -> Self { match disruptions { SearchChDisruptions::Map(m) => m.into_values().map(Into::into).collect(), SearchChDisruptions::Vec(v) => v.into_iter().map(Into::into).collect(), } } } impl Default for SearchChDisruptions { fn default() -> Self { Self::Vec(Vec::new()) } } #[derive(Serialize, Deserialize, Debug, Clone)] pub struct SearchChDisruption { id: String, texts: SearchChDisruptionTexts, // A lot more fields which are not too interesting. } #[derive(Serialize, Deserialize, Debug, Clone)] pub struct SearchChDisruptionTexts { // Also has M and L which seem to be mostly the same to S. Not sure what is the difference. // public-transport-enabler seems to only use S: #[serde(rename = "S")] s: SearchChDisruptionText, } #[derive(Serialize, Deserialize, Debug, Clone)] pub struct SearchChDisruptionText { summary: Option, reason: Option, duration: Option, consequence: Option, recommendation: Option, } impl From for Remark { fn from(disruption: SearchChDisruption) -> Remark { let texts = disruption.texts.s; Remark { code: disruption.id, text: vec![ texts.summary.clone(), texts.reason, texts.duration, texts.consequence, texts.recommendation, ] .into_iter() .flatten() .map(|t| t + ".") .collect::>() .join(" "), r#type: rcore::RemarkType::Status, association: rcore::RemarkAssociation::None, summary: texts.summary, trip_id: None, } } } #[derive(Serialize, Deserialize, Debug, Clone)] pub struct SearchChStop { #[serde(default)] #[serde(with = "serialize::optional_time")] arrival: Option, arr_delay: Option, #[serde(default)] #[serde(with = "serialize::optional_time")] departure: Option, dep_delay: Option, name: String, stopid: String, // x, y, lon: f32, lat: f32, } impl From for IntermediateLocation { fn from(stop: SearchChStop) -> IntermediateLocation { if stop.departure.is_some() { Self::Stop(Stop { place: Place::Station(Station { id: stop.stopid.clone(), name: Some(stop.name.clone()), location: Some(Location::Point { id: Some(stop.stopid), name: Some(stop.name), poi: None, latitude: stop.lat, longitude: stop.lon, }), products: vec![], }), departure: stop .departure .and_then(|d| convert_datetime_with_delay(d, stop.dep_delay.as_ref())), planned_departure: stop.departure.and_then(convert_datetime), arrival: stop .arrival .and_then(|d| convert_datetime_with_delay(d, stop.arr_delay.as_ref())), planned_arrival: stop.arrival.and_then(convert_datetime), // Note: The API does not provide track information for stopovers. arrival_platform: None, planned_arrival_platform: None, departure_platform: None, planned_departure_platform: None, // Note: The API does not provide cancellation or remark information for stopovers. cancelled: false, remarks: vec![], }) } else { Self::Railway(Place::Location(Location::Point { id: Some(stop.stopid), name: Some(stop.name), poi: None, latitude: stop.lat, longitude: stop.lon, })) } } } #[derive(Serialize, Deserialize, Debug, Clone)] pub struct SearchChExit { #[serde(with = "serialize::time")] arrival: chrono::NaiveDateTime, stopid: String, // x, y name: String, // sbb_name, waittime, track: Option, arr_delay: Option, lon: f32, lat: f32, } impl From for JourneysResponse { fn from(response: SearchChJourneysResponse) -> JourneysResponse { Self { earlier_ref: response .connections .first() .and_then(|c| convert_datetime(c.departure)) .map(|t| t.to_rfc3339()), later_ref: response .connections .last() .and_then(|c| convert_datetime(c.departure)) .map(|t| t.to_rfc3339()), journeys: response.connections.into_iter().map(Into::into).collect(), } } } impl From for Journey { fn from(connection: SearchChConnection) -> Self { let mut legs: Vec = connection.legs.into_iter().map(Into::into).collect(); // Note: Last "leg" is always destination. legs.remove(legs.len() - 1); Self { id: legs .iter() .flat_map(|l| l.trip_id.as_ref()) .map(|s| &s[..]) .collect(), legs, price: None, } } } impl From for Leg { fn from(leg: SearchChLeg) -> Leg { let origin = Place::Station(Station { id: leg.stopid.clone(), name: Some(leg.name.clone()), location: Some(Location::Point { id: Some(leg.stopid), name: Some(leg.name), poi: None, latitude: leg.lat, longitude: leg.lon, }), products: vec![], }); let destination = Place::Station(Station { id: leg .exit .as_ref() .map(|e| e.stopid.clone()) .unwrap_or_default(), name: leg.exit.as_ref().map(|e| e.name.clone()), location: Some(Location::Point { id: leg.exit.as_ref().map(|e| e.stopid.clone()), name: leg.exit.as_ref().map(|e| e.name.clone()), poi: None, latitude: leg.exit.as_ref().map(|e| e.lat).unwrap_or_default(), longitude: leg.exit.as_ref().map(|e| e.lon).unwrap_or_default(), }), products: vec![], }); let planned_departure = leg.departure.and_then(convert_datetime); let planned_arrival = leg.exit.as_ref().and_then(|e| convert_datetime(e.arrival)); let departure = leg .departure .and_then(|d| convert_datetime_with_delay(d, leg.dep_delay.as_ref())); let arrival = leg .exit .as_ref() .and_then(|e| convert_datetime_with_delay(e.arrival, e.arr_delay.as_ref())); let arrival_platform = leg.exit.as_ref().and_then(|e| e.track.clone()); let departure_platform = leg.track.clone(); let r#type = leg.r#type.unwrap_or_default(); let mode = type_string_to_mode(&r#type); let mut intermediate_locations = vec![IntermediateLocation::Stop(Stop { place: origin.clone(), departure, planned_departure, arrival: None, planned_arrival: None, arrival_platform: None, planned_arrival_platform: None, // TODO: Track changes // When tracks change, the API does not return which was the old track but only the new one with an exclamation-mark. departure_platform: departure_platform.clone(), planned_departure_platform: departure_platform.clone(), cancelled: false, remarks: vec![], })]; // Note: Should we consider filtering out "Bahn-2000-Strecke" and others. This is no real stopover. // Or should we change semantics of a "stopover" to also include that? // See also and . intermediate_locations.extend(leg.stops.unwrap_or_default().into_iter().map(Into::into)); intermediate_locations.push(IntermediateLocation::Stop(Stop { place: destination.clone(), departure: None, planned_departure: None, arrival, planned_arrival, // TODO: Track changes // When tracks change, the API does not return which was the old track but only the new one with an exclamation-mark. arrival_platform: arrival_platform.clone(), planned_arrival_platform: arrival_platform.clone(), departure_platform: None, planned_departure_platform: None, cancelled: false, remarks: vec![], })); Leg { origin, destination, departure, planned_departure, arrival, planned_arrival, reachable: true, trip_id: leg.tripid, line: if r#type != "walk" { Some(Line { name: leg.star_g.clone(), fahrt_nr: leg.star_l, mode: mode.clone(), product: Product { mode, name: leg.star_g.clone().unwrap_or_default().into(), short: leg.star_g.clone().unwrap_or_default().into(), }, operator: leg.operator.map(|o| Operator { id: o.clone(), name: o.clone(), }), product_name: leg.star_g, }) } else { None }, direction: None, // TODO: Track changes // When tracks change, the API does not return which was the old track but only the new one with an exclamation-mark. arrival_platform: arrival_platform.clone(), planned_arrival_platform: arrival_platform, departure_platform: departure_platform.clone(), planned_departure_platform: departure_platform, intermediate_locations, #[cfg(feature = "polylines")] polyline: None, walking: r#type == "walk", cancelled: leg.cancelled.unwrap_or_default(), remarks: leg.disruptions.unwrap_or_default().into(), // Information not provided. load_factor: None, transfer: false, distance: None, frequency: None, } } }