From a246f0156cb7127a3ca2d0a4f52db945f0b2ed19 Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Sun, 26 Nov 2023 20:08:30 -0700 Subject: [PATCH] init commit --- .gitignore | 1 + .vscode/settings.json | 3 + Cargo.lock | 1319 ++++++++++++++++++++++++++++++++++ Cargo.toml | 16 + build.rs | 5 + proto/transit_realtime.proto | 1035 ++++++++++++++++++++++++++ src/main.rs | 32 + 7 files changed, 2411 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/settings.json create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 build.rs create mode 100644 proto/transit_realtime.proto create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..660eb93 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "rust-analyzer.check.command": "clippy" +} \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..1dee6c3 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1319 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.21.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "encoding_rs" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[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 = "futures-channel" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" + +[[package]] +name = "futures-sink" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" + +[[package]] +name = "futures-task" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" + +[[package]] +name = "futures-util" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "gtfs_realtime_parser" +version = "0.1.0" +dependencies = [ + "bytes", + "prost", + "prost-build", + "reqwest", + "tokio", +] + +[[package]] +name = "h2" +version = "0.3.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" + +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "http" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2 0.4.10", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "js-sys" +version = "0.3.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" + +[[package]] +name = "linux-raw-sys" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "memchr" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +dependencies = [ + "libc", + "wasi", + "windows-sys", +] + +[[package]] +name = "multimap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" + +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "openssl" +version = "0.10.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79a4c6c3a2b158f7f8f2a2fc5a969fa3a068df6fc9dbb4a43845436e3af7c800" +dependencies = [ + "bitflags 2.4.1", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3812c071ba60da8b5677cc12bcb1d42989a65553772897a7e0355545a819838f" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "petgraph" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" + +[[package]] +name = "prettyplease" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" +dependencies = [ + "bytes", + "heck", + "itertools", + "log", + "multimap", + "once_cell", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "regex", + "syn", + "tempfile", + "which", +] + +[[package]] +name = "prost-derive" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-types" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" +dependencies = [ + "prost", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "reqwest" +version = "0.11.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-tls", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustix" +version = "0.38.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" +dependencies = [ + "bitflags 2.4.1", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "schannel" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "security-framework" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "serde" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" + +[[package]] +name = "socket2" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "socket2" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "syn" +version = "2.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2 0.5.5", + "tokio-macros", + "windows-sys", +] + +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" + +[[package]] +name = "web-sys" +version = "0.3.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..7705235 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "gtfs_realtime_parser" +version = "0.1.0" +edition = "2021" +authors = ["Anson Biggs anson@ansonbiggs.com"] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +bytes = "1.5.0" +prost = "0.12" +reqwest = "0.11" +tokio = { version = "1", features = ["full"] } + +[build-dependencies] +prost-build = { version = "0.12" } \ No newline at end of file diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..6ac33ae --- /dev/null +++ b/build.rs @@ -0,0 +1,5 @@ +fn main() { + prost_build::Config::new() + .out_dir(std::env::var("OUT_DIR").unwrap()) + .compile_protos(&["proto/transit_realtime.proto"], &["proto/"]).unwrap(); +} \ No newline at end of file diff --git a/proto/transit_realtime.proto b/proto/transit_realtime.proto new file mode 100644 index 0000000..ca68e84 --- /dev/null +++ b/proto/transit_realtime.proto @@ -0,0 +1,1035 @@ +// Copyright 2015 The GTFS Specifications Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Protocol definition file for GTFS Realtime. +// +// GTFS Realtime lets transit agencies provide consumers with realtime +// information about disruptions to their service (stations closed, lines not +// operating, important delays etc), location of their vehicles and expected +// arrival times. +// +// This protocol is published at: +// https://github.com/google/transit/tree/master/gtfs-realtime + +syntax = "proto2"; +option java_package = "com.google.transit.realtime"; +package transit_realtime; + +// The contents of a feed message. +// A feed is a continuous stream of feed messages. Each message in the stream is +// obtained as a response to an appropriate HTTP GET request. +// A realtime feed is always defined with relation to an existing GTFS feed. +// All the entity ids are resolved with respect to the GTFS feed. +// Note that "required" and "optional" as stated in this file refer to Protocol +// Buffer cardinality, not semantic cardinality. See reference.md at +// https://github.com/google/transit/tree/master/gtfs-realtime for field +// semantic cardinality. +message FeedMessage { + // Metadata about this feed and feed message. + required FeedHeader header = 1; + + // Contents of the feed. + repeated FeedEntity entity = 2; + + // The extensions namespace allows 3rd-party developers to extend the + // GTFS Realtime specification in order to add and evaluate new features and + // modifications to the spec. + extensions 1000 to 1999; + + // The following extension IDs are reserved for private use by any organization. + extensions 9000 to 9999; +} + +// Metadata about a feed, included in feed messages. +message FeedHeader { + // Version of the feed specification. + // The current version is 2.0. Valid versions are "2.0", "1.0". + required string gtfs_realtime_version = 1; + + // Determines whether the current fetch is incremental. Currently, + // DIFFERENTIAL mode is unsupported and behavior is unspecified for feeds + // that use this mode. There are discussions on the GTFS Realtime mailing + // list around fully specifying the behavior of DIFFERENTIAL mode and the + // documentation will be updated when those discussions are finalized. + enum Incrementality { + FULL_DATASET = 0; + DIFFERENTIAL = 1; + } + optional Incrementality incrementality = 2 [default = FULL_DATASET]; + + // This timestamp identifies the moment when the content of this feed has been + // created (in server time). In POSIX time (i.e., number of seconds since + // January 1st 1970 00:00:00 UTC). + optional uint64 timestamp = 3; + + // The extensions namespace allows 3rd-party developers to extend the + // GTFS Realtime specification in order to add and evaluate new features and + // modifications to the spec. + extensions 1000 to 1999; + + // The following extension IDs are reserved for private use by any organization. + extensions 9000 to 9999; +} + +// A definition (or update) of an entity in the transit feed. +message FeedEntity { + // The ids are used only to provide incrementality support. The id should be + // unique within a FeedMessage. Consequent FeedMessages may contain + // FeedEntities with the same id. In case of a DIFFERENTIAL update the new + // FeedEntity with some id will replace the old FeedEntity with the same id + // (or delete it - see is_deleted below). + // The actual GTFS entities (e.g. stations, routes, trips) referenced by the + // feed must be specified by explicit selectors (see EntitySelector below for + // more info). + required string id = 1; + + // Whether this entity is to be deleted. Relevant only for incremental + // fetches. + optional bool is_deleted = 2 [default = false]; + + // Data about the entity itself. Exactly one of the following fields must be + // present (unless the entity is being deleted). + optional TripUpdate trip_update = 3; + optional VehiclePosition vehicle = 4; + optional Alert alert = 5; + + // NOTE: This field is still experimental, and subject to change. It may be formally adopted in the future. + optional Shape shape = 6; + + // The extensions namespace allows 3rd-party developers to extend the + // GTFS Realtime Specification in order to add and evaluate new features and + // modifications to the spec. + extensions 1000 to 1999; + + // The following extension IDs are reserved for private use by any organization. + extensions 9000 to 9999; +} + +// +// Entities used in the feed. +// + +// Realtime update of the progress of a vehicle along a trip. +// Depending on the value of ScheduleRelationship, a TripUpdate can specify: +// - A trip that proceeds along the schedule. +// - A trip that proceeds along a route but has no fixed schedule. +// - A trip that have been added or removed with regard to schedule. +// +// The updates can be for future, predicted arrival/departure events, or for +// past events that already occurred. +// Normally, updates should get more precise and more certain (see +// uncertainty below) as the events gets closer to current time. +// Even if that is not possible, the information for past events should be +// precise and certain. In particular, if an update points to time in the past +// but its update's uncertainty is not 0, the client should conclude that the +// update is a (wrong) prediction and that the trip has not completed yet. +// +// Note that the update can describe a trip that is already completed. +// To this end, it is enough to provide an update for the last stop of the trip. +// If the time of that is in the past, the client will conclude from that that +// the whole trip is in the past (it is possible, although inconsequential, to +// also provide updates for preceding stops). +// This option is most relevant for a trip that has completed ahead of schedule, +// but according to the schedule, the trip is still proceeding at the current +// time. Removing the updates for this trip could make the client assume +// that the trip is still proceeding. +// Note that the feed provider is allowed, but not required, to purge past +// updates - this is one case where this would be practically useful. +message TripUpdate { + // The Trip that this message applies to. There can be at most one + // TripUpdate entity for each actual trip instance. + // If there is none, that means there is no prediction information available. + // It does *not* mean that the trip is progressing according to schedule. + required TripDescriptor trip = 1; + + // Additional information on the vehicle that is serving this trip. + optional VehicleDescriptor vehicle = 3; + + // Timing information for a single predicted event (either arrival or + // departure). + // Timing consists of delay and/or estimated time, and uncertainty. + // - delay should be used when the prediction is given relative to some + // existing schedule in GTFS. + // - time should be given whether there is a predicted schedule or not. If + // both time and delay are specified, time will take precedence + // (although normally, time, if given for a scheduled trip, should be + // equal to scheduled time in GTFS + delay). + // + // Uncertainty applies equally to both time and delay. + // The uncertainty roughly specifies the expected error in true delay (but + // note, we don't yet define its precise statistical meaning). It's possible + // for the uncertainty to be 0, for example for trains that are driven under + // computer timing control. + message StopTimeEvent { + // Delay (in seconds) can be positive (meaning that the vehicle is late) or + // negative (meaning that the vehicle is ahead of schedule). Delay of 0 + // means that the vehicle is exactly on time. + optional int32 delay = 1; + + // Event as absolute time. + // In Unix time (i.e., number of seconds since January 1st 1970 00:00:00 + // UTC). + optional int64 time = 2; + + // If uncertainty is omitted, it is interpreted as unknown. + // If the prediction is unknown or too uncertain, the delay (or time) field + // should be empty. In such case, the uncertainty field is ignored. + // To specify a completely certain prediction, set its uncertainty to 0. + optional int32 uncertainty = 3; + + // The extensions namespace allows 3rd-party developers to extend the + // GTFS Realtime Specification in order to add and evaluate new features + // and modifications to the spec. + extensions 1000 to 1999; + + // The following extension IDs are reserved for private use by any organization. + extensions 9000 to 9999; + } + + // Realtime update for arrival and/or departure events for a given stop on a + // trip. Updates can be supplied for both past and future events. + // The producer is allowed, although not required, to drop past events. + message StopTimeUpdate { + // The update is linked to a specific stop either through stop_sequence or + // stop_id, so one of the fields below must necessarily be set. + // See the documentation in TripDescriptor for more information. + + // Must be the same as in stop_times.txt in the corresponding GTFS feed. + optional uint32 stop_sequence = 1; + // Must be the same as in stops.txt in the corresponding GTFS feed. + optional string stop_id = 4; + + optional StopTimeEvent arrival = 2; + optional StopTimeEvent departure = 3; + + // Expected occupancy after departure from the given stop. + // Should be provided only for future stops. + // In order to provide departure_occupancy_status without either arrival or + // departure StopTimeEvents, ScheduleRelationship should be set to NO_DATA. + optional VehiclePosition.OccupancyStatus departure_occupancy_status = 7; + + // The relation between the StopTimeEvents and the static schedule. + enum ScheduleRelationship { + // The vehicle is proceeding in accordance with its static schedule of + // stops, although not necessarily according to the times of the schedule. + // At least one of arrival and departure must be provided. If the schedule + // for this stop contains both arrival and departure times then so must + // this update. Frequency-based trips (GTFS frequencies.txt with exact_times = 0) + // should not have a SCHEDULED value and should use UNSCHEDULED instead. + SCHEDULED = 0; + + // The stop is skipped, i.e., the vehicle will not stop at this stop. + // Arrival and departure are optional. + SKIPPED = 1; + + // No StopTimeEvents are given for this stop. + // The main intention for this value is to give time predictions only for + // part of a trip, i.e., if the last update for a trip has a NO_DATA + // specifier, then StopTimeEvents for the rest of the stops in the trip + // are considered to be unspecified as well. + // Neither arrival nor departure should be supplied. + NO_DATA = 2; + + // The vehicle is operating a trip defined in GTFS frequencies.txt with exact_times = 0. + // This value should not be used for trips that are not defined in GTFS frequencies.txt, + // or trips in GTFS frequencies.txt with exact_times = 1. Trips containing StopTimeUpdates + // with ScheduleRelationship=UNSCHEDULED must also set TripDescriptor.ScheduleRelationship=UNSCHEDULED. + // NOTE: This field is still experimental, and subject to change. It may be + // formally adopted in the future. + UNSCHEDULED = 3; + } + optional ScheduleRelationship schedule_relationship = 5 + [default = SCHEDULED]; + + // Provides the updated values for the stop time. + // NOTE: This message is still experimental, and subject to change. It may be formally adopted in the future. + message StopTimeProperties { + // Supports real-time stop assignments. Refers to a stop_id defined in the GTFS stops.txt. + // The new assigned_stop_id should not result in a significantly different trip experience for the end user than + // the stop_id defined in GTFS stop_times.txt. In other words, the end user should not view this new stop_id as an + // "unusual change" if the new stop was presented within an app without any additional context. + // For example, this field is intended to be used for platform assignments by using a stop_id that belongs to the + // same station as the stop originally defined in GTFS stop_times.txt. + // To assign a stop without providing any real-time arrival or departure predictions, populate this field and set + // StopTimeUpdate.schedule_relationship = NO_DATA. + // If this field is populated, it is preferred to omit `StopTimeUpdate.stop_id` and use only `StopTimeUpdate.stop_sequence`. If + // `StopTimeProperties.assigned_stop_id` and `StopTimeUpdate.stop_id` are populated, `StopTimeUpdate.stop_id` must match `assigned_stop_id`. + // Platform assignments should be reflected in other GTFS-realtime fields as well + // (e.g., `VehiclePosition.stop_id`). + // NOTE: This field is still experimental, and subject to change. It may be formally adopted in the future. + optional string assigned_stop_id = 1; + + // The extensions namespace allows 3rd-party developers to extend the + // GTFS Realtime Specification in order to add and evaluate new features + // and modifications to the spec. + extensions 1000 to 1999; + + // The following extension IDs are reserved for private use by any organization. + extensions 9000 to 9999; + } + + // Realtime updates for certain properties defined within GTFS stop_times.txt + // NOTE: This field is still experimental, and subject to change. It may be formally adopted in the future. + optional StopTimeProperties stop_time_properties = 6; + + // The extensions namespace allows 3rd-party developers to extend the + // GTFS Realtime Specification in order to add and evaluate new features + // and modifications to the spec. + extensions 1000 to 1999; + + // The following extension IDs are reserved for private use by any organization. + extensions 9000 to 9999; + } + + // Updates to StopTimes for the trip (both future, i.e., predictions, and in + // some cases, past ones, i.e., those that already happened). + // The updates must be sorted by stop_sequence, and apply for all the + // following stops of the trip up to the next specified one. + // + // Example 1: + // For a trip with 20 stops, a StopTimeUpdate with arrival delay and departure + // delay of 0 for stop_sequence of the current stop means that the trip is + // exactly on time. + // + // Example 2: + // For the same trip instance, 3 StopTimeUpdates are provided: + // - delay of 5 min for stop_sequence 3 + // - delay of 1 min for stop_sequence 8 + // - delay of unspecified duration for stop_sequence 10 + // This will be interpreted as: + // - stop_sequences 3,4,5,6,7 have delay of 5 min. + // - stop_sequences 8,9 have delay of 1 min. + // - stop_sequences 10,... have unknown delay. + repeated StopTimeUpdate stop_time_update = 2; + + // The most recent moment at which the vehicle's real-time progress was measured + // to estimate StopTimes in the future. When StopTimes in the past are provided, + // arrival/departure times may be earlier than this value. In POSIX + // time (i.e., the number of seconds since January 1st 1970 00:00:00 UTC). + optional uint64 timestamp = 4; + + // The current schedule deviation for the trip. Delay should only be + // specified when the prediction is given relative to some existing schedule + // in GTFS. + // + // Delay (in seconds) can be positive (meaning that the vehicle is late) or + // negative (meaning that the vehicle is ahead of schedule). Delay of 0 + // means that the vehicle is exactly on time. + // + // Delay information in StopTimeUpdates take precedent of trip-level delay + // information, such that trip-level delay is only propagated until the next + // stop along the trip with a StopTimeUpdate delay value specified. + // + // Feed providers are strongly encouraged to provide a TripUpdate.timestamp + // value indicating when the delay value was last updated, in order to + // evaluate the freshness of the data. + // + // NOTE: This field is still experimental, and subject to change. It may be + // formally adopted in the future. + optional int32 delay = 5; + + // Defines updated properties of the trip, such as a new shape_id when there is a detour. Or defines the + // trip_id, start_date, and start_time of a DUPLICATED trip. + // NOTE: This message is still experimental, and subject to change. It may be formally adopted in the future. + message TripProperties { + // Defines the identifier of a new trip that is a duplicate of an existing trip defined in (CSV) GTFS trips.txt + // but will start at a different service date and/or time (defined using the TripProperties.start_date and + // TripProperties.start_time fields). See definition of trips.trip_id in (CSV) GTFS. Its value must be different + // than the ones used in the (CSV) GTFS. Required if schedule_relationship=DUPLICATED, otherwise this field must not + // be populated and will be ignored by consumers. + // NOTE: This field is still experimental, and subject to change. It may be formally adopted in the future. + optional string trip_id = 1; + // Service date on which the DUPLICATED trip will be run, in YYYYMMDD format. Required if + // schedule_relationship=DUPLICATED, otherwise this field must not be populated and will be ignored by consumers. + // NOTE: This field is still experimental, and subject to change. It may be formally adopted in the future. + optional string start_date = 2; + // Defines the departure start time of the trip when it’s duplicated. See definition of stop_times.departure_time + // in (CSV) GTFS. Scheduled arrival and departure times for the duplicated trip are calculated based on the offset + // between the original trip departure_time and this field. For example, if a GTFS trip has stop A with a + // departure_time of 10:00:00 and stop B with departure_time of 10:01:00, and this field is populated with the value + // of 10:30:00, stop B on the duplicated trip will have a scheduled departure_time of 10:31:00. Real-time prediction + // delay values are applied to this calculated schedule time to determine the predicted time. For example, if a + // departure delay of 30 is provided for stop B, then the predicted departure time is 10:31:30. Real-time + // prediction time values do not have any offset applied to them and indicate the predicted time as provided. + // For example, if a departure time representing 10:31:30 is provided for stop B, then the predicted departure time + // is 10:31:30. This field is required if schedule_relationship is DUPLICATED, otherwise this field must not be + // populated and will be ignored by consumers. + // NOTE: This field is still experimental, and subject to change. It may be formally adopted in the future. + optional string start_time = 3; + // Specifies the shape of the vehicle travel path when the trip shape differs from the shape specified in + // (CSV) GTFS or to specify it in real-time when it's not provided by (CSV) GTFS, such as a vehicle that takes differing + // paths based on rider demand. See definition of trips.shape_id in (CSV) GTFS. If a shape is neither defined in (CSV) GTFS + // nor in real-time, the shape is considered unknown. This field can refer to a shape defined in the (CSV) GTFS in shapes.txt + // or a Shape in the (protobuf) real-time feed. The order of stops (stop sequences) for this trip must remain the same as + // (CSV) GTFS. Stops that are a part of the original trip but will no longer be made, such as when a detour occurs, should + // be marked as schedule_relationship=SKIPPED. + // NOTE: This field is still experimental, and subject to change. It may be formally adopted in the future. + optional string shape_id = 4; + + // The extensions namespace allows 3rd-party developers to extend the + // GTFS Realtime Specification in order to add and evaluate new features + // and modifications to the spec. + extensions 1000 to 1999; + + // The following extension IDs are reserved for private use by any organization. + extensions 9000 to 9999; + } + optional TripProperties trip_properties = 6; + + // The extensions namespace allows 3rd-party developers to extend the + // GTFS Realtime Specification in order to add and evaluate new features and + // modifications to the spec. + extensions 1000 to 1999; + + // The following extension IDs are reserved for private use by any organization. + extensions 9000 to 9999; +} + +// Realtime positioning information for a given vehicle. +message VehiclePosition { + // The Trip that this vehicle is serving. + // Can be empty or partial if the vehicle can not be identified with a given + // trip instance. + optional TripDescriptor trip = 1; + + // Additional information on the vehicle that is serving this trip. + optional VehicleDescriptor vehicle = 8; + + // Current position of this vehicle. + optional Position position = 2; + + // The stop sequence index of the current stop. The meaning of + // current_stop_sequence (i.e., the stop that it refers to) is determined by + // current_status. + // If current_status is missing IN_TRANSIT_TO is assumed. + optional uint32 current_stop_sequence = 3; + // Identifies the current stop. The value must be the same as in stops.txt in + // the corresponding GTFS feed. + optional string stop_id = 7; + + enum VehicleStopStatus { + // The vehicle is just about to arrive at the stop (on a stop + // display, the vehicle symbol typically flashes). + INCOMING_AT = 0; + + // The vehicle is standing at the stop. + STOPPED_AT = 1; + + // The vehicle has departed and is in transit to the next stop. + IN_TRANSIT_TO = 2; + } + // The exact status of the vehicle with respect to the current stop. + // Ignored if current_stop_sequence is missing. + optional VehicleStopStatus current_status = 4 [default = IN_TRANSIT_TO]; + + // Moment at which the vehicle's position was measured. In POSIX time + // (i.e., number of seconds since January 1st 1970 00:00:00 UTC). + optional uint64 timestamp = 5; + + // Congestion level that is affecting this vehicle. + enum CongestionLevel { + UNKNOWN_CONGESTION_LEVEL = 0; + RUNNING_SMOOTHLY = 1; + STOP_AND_GO = 2; + CONGESTION = 3; + SEVERE_CONGESTION = 4; // People leaving their cars. + } + optional CongestionLevel congestion_level = 6; + + // The state of passenger occupancy for the vehicle or carriage. + // Individual producers may not publish all OccupancyStatus values. Therefore, consumers + // must not assume that the OccupancyStatus values follow a linear scale. + // Consumers should represent OccupancyStatus values as the state indicated + // and intended by the producer. Likewise, producers must use OccupancyStatus values that + // correspond to actual vehicle occupancy states. + // For describing passenger occupancy levels on a linear scale, see `occupancy_percentage`. + // This field is still experimental, and subject to change. It may be formally adopted in the future. + enum OccupancyStatus { + // The vehicle or carriage is considered empty by most measures, and has few or no + // passengers onboard, but is still accepting passengers. + EMPTY = 0; + + // The vehicle or carriage has a large number of seats available. + // The amount of free seats out of the total seats available to be + // considered large enough to fall into this category is determined at the + // discretion of the producer. + MANY_SEATS_AVAILABLE = 1; + + // The vehicle or carriage has a relatively small number of seats available. + // The amount of free seats out of the total seats available to be + // considered small enough to fall into this category is determined at the + // discretion of the feed producer. + FEW_SEATS_AVAILABLE = 2; + + // The vehicle or carriage can currently accommodate only standing passengers. + STANDING_ROOM_ONLY = 3; + + // The vehicle or carriage can currently accommodate only standing passengers + // and has limited space for them. + CRUSHED_STANDING_ROOM_ONLY = 4; + + // The vehicle or carriage is considered full by most measures, but may still be + // allowing passengers to board. + FULL = 5; + + // The vehicle or carriage is not accepting passengers, but usually accepts passengers for boarding. + NOT_ACCEPTING_PASSENGERS = 6; + + // The vehicle or carriage doesn't have any occupancy data available at that time. + NO_DATA_AVAILABLE = 7; + + // The vehicle or carriage is not boardable and never accepts passengers. + // Useful for special vehicles or carriages (engine, maintenance carriage, etc…). + NOT_BOARDABLE = 8; + + } + // If multi_carriage_status is populated with per-carriage OccupancyStatus, + // then this field should describe the entire vehicle with all carriages accepting passengers considered. + optional OccupancyStatus occupancy_status = 9; + + // A percentage value indicating the degree of passenger occupancy in the vehicle. + // The values are represented as an integer without decimals. 0 means 0% and 100 means 100%. + // The value 100 should represent the total maximum occupancy the vehicle was designed for, + // including both seated and standing capacity, and current operating regulations allow. + // The value may exceed 100 if there are more passengers than the maximum designed capacity. + // The precision of occupancy_percentage should be low enough that individual passengers cannot be tracked boarding or alighting the vehicle. + // If multi_carriage_status is populated with per-carriage occupancy_percentage, + // then this field should describe the entire vehicle with all carriages accepting passengers considered. + // This field is still experimental, and subject to change. It may be formally adopted in the future. + optional uint32 occupancy_percentage = 10; + + // Carriage specific details, used for vehicles composed of several carriages + // This message/field is still experimental, and subject to change. It may be formally adopted in the future. + message CarriageDetails { + + // Identification of the carriage. Should be unique per vehicle. + optional string id = 1; + + // User visible label that may be shown to the passenger to help identify + // the carriage. Example: "7712", "Car ABC-32", etc... + // This message/field is still experimental, and subject to change. It may be formally adopted in the future. + optional string label = 2; + + // Occupancy status for this given carriage, in this vehicle + // This message/field is still experimental, and subject to change. It may be formally adopted in the future. + optional OccupancyStatus occupancy_status = 3 [default = NO_DATA_AVAILABLE]; + + // Occupancy percentage for this given carriage, in this vehicle. + // Follows the same rules as "VehiclePosition.occupancy_percentage" + // -1 in case data is not available for this given carriage (as protobuf defaults to 0 otherwise) + // This message/field is still experimental, and subject to change. It may be formally adopted in the future. + optional int32 occupancy_percentage = 4 [default = -1]; + + // Identifies the order of this carriage with respect to the other + // carriages in the vehicle's list of CarriageDetails. + // The first carriage in the direction of travel must have a value of 1. + // The second value corresponds to the second carriage in the direction + // of travel and must have a value of 2, and so forth. + // For example, the first carriage in the direction of travel has a value of 1. + // If the second carriage in the direction of travel has a value of 3, + // consumers will discard data for all carriages (i.e., the multi_carriage_details field). + // Carriages without data must be represented with a valid carriage_sequence number and the fields + // without data should be omitted (alternately, those fields could also be included and set to the "no data" values). + // This message/field is still experimental, and subject to change. It may be formally adopted in the future. + optional uint32 carriage_sequence = 5; + + // The extensions namespace allows 3rd-party developers to extend the + // GTFS Realtime Specification in order to add and evaluate new features and + // modifications to the spec. + extensions 1000 to 1999; + + // The following extension IDs are reserved for private use by any organization. + extensions 9000 to 9999; + } + + // Details of the multiple carriages of this given vehicle. + // The first occurrence represents the first carriage of the vehicle, + // given the current direction of travel. + // The number of occurrences of the multi_carriage_details + // field represents the number of carriages of the vehicle. + // It also includes non boardable carriages, + // like engines, maintenance carriages, etc… as they provide valuable + // information to passengers about where to stand on a platform. + // This message/field is still experimental, and subject to change. It may be formally adopted in the future. + repeated CarriageDetails multi_carriage_details = 11; + + // The extensions namespace allows 3rd-party developers to extend the + // GTFS Realtime Specification in order to add and evaluate new features and + // modifications to the spec. + extensions 1000 to 1999; + + // The following extension IDs are reserved for private use by any organization. + extensions 9000 to 9999; +} + +// An alert, indicating some sort of incident in the public transit network. +message Alert { + // Time when the alert should be shown to the user. If missing, the + // alert will be shown as long as it appears in the feed. + // If multiple ranges are given, the alert will be shown during all of them. + repeated TimeRange active_period = 1; + + // Entities whose users we should notify of this alert. + repeated EntitySelector informed_entity = 5; + + // Cause of this alert. If cause_detail is included, then Cause must also be included. + enum Cause { + UNKNOWN_CAUSE = 1; + OTHER_CAUSE = 2; // Not machine-representable. + TECHNICAL_PROBLEM = 3; + STRIKE = 4; // Public transit agency employees stopped working. + DEMONSTRATION = 5; // People are blocking the streets. + ACCIDENT = 6; + HOLIDAY = 7; + WEATHER = 8; + MAINTENANCE = 9; + CONSTRUCTION = 10; + POLICE_ACTIVITY = 11; + MEDICAL_EMERGENCY = 12; + } + optional Cause cause = 6 [default = UNKNOWN_CAUSE]; + + // What is the effect of this problem on the affected entity. If effect_detail is included, then Effect must also be included. + enum Effect { + NO_SERVICE = 1; + REDUCED_SERVICE = 2; + + // We don't care about INsignificant delays: they are hard to detect, have + // little impact on the user, and would clutter the results as they are too + // frequent. + SIGNIFICANT_DELAYS = 3; + + DETOUR = 4; + ADDITIONAL_SERVICE = 5; + MODIFIED_SERVICE = 6; + OTHER_EFFECT = 7; + UNKNOWN_EFFECT = 8; + STOP_MOVED = 9; + NO_EFFECT = 10; + ACCESSIBILITY_ISSUE = 11; + } + optional Effect effect = 7 [default = UNKNOWN_EFFECT]; + + // The URL which provides additional information about the alert. + optional TranslatedString url = 8; + + // Alert header. Contains a short summary of the alert text as plain-text. + optional TranslatedString header_text = 10; + + // Full description for the alert as plain-text. The information in the + // description should add to the information of the header. + optional TranslatedString description_text = 11; + + // Text for alert header to be used in text-to-speech implementations. This field is the text-to-speech version of header_text. + optional TranslatedString tts_header_text = 12; + + // Text for full description for the alert to be used in text-to-speech implementations. This field is the text-to-speech version of description_text. + optional TranslatedString tts_description_text = 13; + + // Severity of this alert. + enum SeverityLevel { + UNKNOWN_SEVERITY = 1; + INFO = 2; + WARNING = 3; + SEVERE = 4; + } + + optional SeverityLevel severity_level = 14 [default = UNKNOWN_SEVERITY]; + + // TranslatedImage to be displayed along the alert text. Used to explain visually the alert effect of a detour, station closure, etc. The image must enhance the understanding of the alert. Any essential information communicated within the image must also be contained in the alert text. + // The following types of images are discouraged : image containing mainly text, marketing or branded images that add no additional information. + // NOTE: This field is still experimental, and subject to change. It may be formally adopted in the future. + optional TranslatedImage image = 15; + + // Text describing the appearance of the linked image in the `image` field (e.g., in case the image can't be displayed + // or the user can't see the image for accessibility reasons). See the HTML spec for alt image text - https://html.spec.whatwg.org/#alt. + // NOTE: This field is still experimental, and subject to change. It may be formally adopted in the future. + optional TranslatedString image_alternative_text = 16; + + + // Description of the cause of the alert that allows for agency-specific language; more specific than the Cause. If cause_detail is included, then Cause must also be included. + // NOTE: This field is still experimental, and subject to change. It may be formally adopted in the future. + optional TranslatedString cause_detail = 17; + + // Description of the effect of the alert that allows for agency-specific language; more specific than the Effect. If effect_detail is included, then Effect must also be included. + // NOTE: This field is still experimental, and subject to change. It may be formally adopted in the future. + optional TranslatedString effect_detail = 18; + + // The extensions namespace allows 3rd-party developers to extend the + // GTFS Realtime Specification in order to add and evaluate new features + // and modifications to the spec. + extensions 1000 to 1999; + + // The following extension IDs are reserved for private use by any organization. + extensions 9000 to 9999; +} + +// +// Low level data structures used above. +// + +// A time interval. The interval is considered active at time 't' if 't' is +// greater than or equal to the start time and less than the end time. +message TimeRange { + // Start time, in POSIX time (i.e., number of seconds since January 1st 1970 + // 00:00:00 UTC). + // If missing, the interval starts at minus infinity. + optional uint64 start = 1; + + // End time, in POSIX time (i.e., number of seconds since January 1st 1970 + // 00:00:00 UTC). + // If missing, the interval ends at plus infinity. + optional uint64 end = 2; + + // The extensions namespace allows 3rd-party developers to extend the + // GTFS Realtime Specification in order to add and evaluate new features and + // modifications to the spec. + extensions 1000 to 1999; + + // The following extension IDs are reserved for private use by any organization. + extensions 9000 to 9999; +} + +// A position. +message Position { + // Degrees North, in the WGS-84 coordinate system. + required float latitude = 1; + + // Degrees East, in the WGS-84 coordinate system. + required float longitude = 2; + + // Bearing, in degrees, clockwise from North, i.e., 0 is North and 90 is East. + // This can be the compass bearing, or the direction towards the next stop + // or intermediate location. + // This should not be direction deduced from the sequence of previous + // positions, which can be computed from previous data. + optional float bearing = 3; + + // Odometer value, in meters. + optional double odometer = 4; + // Momentary speed measured by the vehicle, in meters per second. + optional float speed = 5; + + // The extensions namespace allows 3rd-party developers to extend the + // GTFS Realtime Specification in order to add and evaluate new features and + // modifications to the spec. + extensions 1000 to 1999; + + // The following extension IDs are reserved for private use by any organization. + extensions 9000 to 9999; +} + +// A descriptor that identifies an instance of a GTFS trip, or all instances of +// a trip along a route. +// - To specify a single trip instance, the trip_id (and if necessary, +// start_time) is set. If route_id is also set, then it should be same as one +// that the given trip corresponds to. +// - To specify all the trips along a given route, only the route_id should be +// set. Note that if the trip_id is not known, then stop sequence ids in +// TripUpdate are not sufficient, and stop_ids must be provided as well. In +// addition, absolute arrival/departure times must be provided. +message TripDescriptor { + // The trip_id from the GTFS feed that this selector refers to. + // For non frequency-based trips, this field is enough to uniquely identify + // the trip. For frequency-based trip, start_time and start_date might also be + // necessary. When schedule_relationship is DUPLICATED within a TripUpdate, the trip_id identifies the trip from + // static GTFS to be duplicated. When schedule_relationship is DUPLICATED within a VehiclePosition, the trip_id + // identifies the new duplicate trip and must contain the value for the corresponding TripUpdate.TripProperties.trip_id. + optional string trip_id = 1; + + // The route_id from the GTFS that this selector refers to. + optional string route_id = 5; + + // The direction_id from the GTFS feed trips.txt file, indicating the + // direction of travel for trips this selector refers to. + optional uint32 direction_id = 6; + + // The initially scheduled start time of this trip instance. + // When the trip_id corresponds to a non-frequency-based trip, this field + // should either be omitted or be equal to the value in the GTFS feed. When + // the trip_id correponds to a frequency-based trip, the start_time must be + // specified for trip updates and vehicle positions. If the trip corresponds + // to exact_times=1 GTFS record, then start_time must be some multiple + // (including zero) of headway_secs later than frequencies.txt start_time for + // the corresponding time period. If the trip corresponds to exact_times=0, + // then its start_time may be arbitrary, and is initially expected to be the + // first departure of the trip. Once established, the start_time of this + // frequency-based trip should be considered immutable, even if the first + // departure time changes -- that time change may instead be reflected in a + // StopTimeUpdate. + // Format and semantics of the field is same as that of + // GTFS/frequencies.txt/start_time, e.g., 11:15:35 or 25:15:35. + optional string start_time = 2; + // The scheduled start date of this trip instance. + // Must be provided to disambiguate trips that are so late as to collide with + // a scheduled trip on a next day. For example, for a train that departs 8:00 + // and 20:00 every day, and is 12 hours late, there would be two distinct + // trips on the same time. + // This field can be provided but is not mandatory for schedules in which such + // collisions are impossible - for example, a service running on hourly + // schedule where a vehicle that is one hour late is not considered to be + // related to schedule anymore. + // In YYYYMMDD format. + optional string start_date = 3; + + // The relation between this trip and the static schedule. If a trip is done + // in accordance with temporary schedule, not reflected in GTFS, then it + // shouldn't be marked as SCHEDULED, but likely as ADDED. + enum ScheduleRelationship { + // Trip that is running in accordance with its GTFS schedule, or is close + // enough to the scheduled trip to be associated with it. + SCHEDULED = 0; + + // An extra trip that was added in addition to a running schedule, for + // example, to replace a broken vehicle or to respond to sudden passenger + // load. + // NOTE: Currently, behavior is unspecified for feeds that use this mode. There are discussions on the GTFS GitHub + // [(1)](https://github.com/google/transit/issues/106) [(2)](https://github.com/google/transit/pull/221) + // [(3)](https://github.com/google/transit/pull/219) around fully specifying or deprecating ADDED trips and the + // documentation will be updated when those discussions are finalized. + ADDED = 1; + + // A trip that is running with no schedule associated to it (GTFS frequencies.txt exact_times=0). + // Trips with ScheduleRelationship=UNSCHEDULED must also set all StopTimeUpdates.ScheduleRelationship=UNSCHEDULED. + UNSCHEDULED = 2; + + // A trip that existed in the schedule but was removed. + CANCELED = 3; + + // Should not be used - for backwards-compatibility only. + REPLACEMENT = 5 [deprecated=true]; + + // An extra trip that was added in addition to a running schedule, for example, to replace a broken vehicle or to + // respond to sudden passenger load. Used with TripUpdate.TripProperties.trip_id, TripUpdate.TripProperties.start_date, + // and TripUpdate.TripProperties.start_time to copy an existing trip from static GTFS but start at a different service + // date and/or time. Duplicating a trip is allowed if the service related to the original trip in (CSV) GTFS + // (in calendar.txt or calendar_dates.txt) is operating within the next 30 days. The trip to be duplicated is + // identified via TripUpdate.TripDescriptor.trip_id. This enumeration does not modify the existing trip referenced by + // TripUpdate.TripDescriptor.trip_id - if a producer wants to cancel the original trip, it must publish a separate + // TripUpdate with the value of CANCELED or DELETED. Trips defined in GTFS frequencies.txt with exact_times that is + // empty or equal to 0 cannot be duplicated. The VehiclePosition.TripDescriptor.trip_id for the new trip must contain + // the matching value from TripUpdate.TripProperties.trip_id and VehiclePosition.TripDescriptor.ScheduleRelationship + // must also be set to DUPLICATED. + // Existing producers and consumers that were using the ADDED enumeration to represent duplicated trips must follow + // the migration guide (https://github.com/google/transit/tree/master/gtfs-realtime/spec/en/examples/migration-duplicated.md) + // to transition to the DUPLICATED enumeration. + // NOTE: This field is still experimental, and subject to change. It may be formally adopted in the future. + DUPLICATED = 6; + + + // A trip that existed in the schedule but was removed and must not be shown to users. + // DELETED should be used instead of CANCELED to indicate that a transit provider would like to entirely remove + // information about the corresponding trip from consuming applications, so the trip is not shown as cancelled to + // riders, e.g. a trip that is entirely being replaced by another trip. + // This designation becomes particularly important if several trips are cancelled and replaced with substitute service. + // If consumers were to show explicit information about the cancellations it would distract from the more important + // real-time predictions. + // NOTE: This field is still experimental, and subject to change. It may be formally adopted in the future. + DELETED = 7; + } + optional ScheduleRelationship schedule_relationship = 4; + + // The extensions namespace allows 3rd-party developers to extend the + // GTFS Realtime Specification in order to add and evaluate new features and + // modifications to the spec. + extensions 1000 to 1999; + + // The following extension IDs are reserved for private use by any organization. + extensions 9000 to 9999; +} + +// Identification information for the vehicle performing the trip. +message VehicleDescriptor { + // Internal system identification of the vehicle. Should be unique per + // vehicle, and can be used for tracking the vehicle as it proceeds through + // the system. + optional string id = 1; + + // User visible label, i.e., something that must be shown to the passenger to + // help identify the correct vehicle. + optional string label = 2; + + // The license plate of the vehicle. + optional string license_plate = 3; + + enum WheelchairAccessible { + // The trip doesn't have information about wheelchair accessibility. + // This is the **default** behavior. If the static GTFS contains a + // _wheelchair_accessible_ value, it won't be overwritten. + NO_VALUE = 0; + + // The trip has no accessibility value present. + // This value will overwrite the value from the GTFS. + UNKNOWN = 1; + + // The trip is wheelchair accessible. + // This value will overwrite the value from the GTFS. + WHEELCHAIR_ACCESSIBLE = 2; + + // The trip is **not** wheelchair accessible. + // This value will overwrite the value from the GTFS. + WHEELCHAIR_INACCESSIBLE = 3; + } + optional WheelchairAccessible wheelchair_accessible = 4 [default = NO_VALUE]; + + // The extensions namespace allows 3rd-party developers to extend the + // GTFS Realtime Specification in order to add and evaluate new features and + // modifications to the spec. + extensions 1000 to 1999; + + // The following extension IDs are reserved for private use by any organization. + extensions 9000 to 9999; +} + +// A selector for an entity in a GTFS feed. +message EntitySelector { + // The values of the fields should correspond to the appropriate fields in the + // GTFS feed. + // At least one specifier must be given. If several are given, then the + // matching has to apply to all the given specifiers. + optional string agency_id = 1; + optional string route_id = 2; + // corresponds to route_type in GTFS. + optional int32 route_type = 3; + optional TripDescriptor trip = 4; + optional string stop_id = 5; + // Corresponds to trip direction_id in GTFS trips.txt. If provided the + // route_id must also be provided. + optional uint32 direction_id = 6; + + // The extensions namespace allows 3rd-party developers to extend the + // GTFS Realtime Specification in order to add and evaluate new features and + // modifications to the spec. + extensions 1000 to 1999; + + // The following extension IDs are reserved for private use by any organization. + extensions 9000 to 9999; +} + +// An internationalized message containing per-language versions of a snippet of +// text or a URL. +// One of the strings from a message will be picked up. The resolution proceeds +// as follows: +// 1. If the UI language matches the language code of a translation, +// the first matching translation is picked. +// 2. If a default UI language (e.g., English) matches the language code of a +// translation, the first matching translation is picked. +// 3. If some translation has an unspecified language code, that translation is +// picked. +message TranslatedString { + message Translation { + // A UTF-8 string containing the message. + required string text = 1; + // BCP-47 language code. Can be omitted if the language is unknown or if + // no i18n is done at all for the feed. At most one translation is + // allowed to have an unspecified language tag. + optional string language = 2; + + // The extensions namespace allows 3rd-party developers to extend the + // GTFS Realtime Specification in order to add and evaluate new features and + // modifications to the spec. + extensions 1000 to 1999; + + // The following extension IDs are reserved for private use by any organization. + extensions 9000 to 9999; + } + // At least one translation must be provided. + repeated Translation translation = 1; + + // The extensions namespace allows 3rd-party developers to extend the + // GTFS Realtime Specification in order to add and evaluate new features and + // modifications to the spec. + extensions 1000 to 1999; + + // The following extension IDs are reserved for private use by any organization. + extensions 9000 to 9999; +} + +// An internationalized image containing per-language versions of a URL linking to an image +// along with meta information +// Only one of the images from a message will be retained by consumers. The resolution proceeds +// as follows: +// 1. If the UI language matches the language code of a translation, +// the first matching translation is picked. +// 2. If a default UI language (e.g., English) matches the language code of a +// translation, the first matching translation is picked. +// 3. If some translation has an unspecified language code, that translation is +// picked. +// NOTE: This field is still experimental, and subject to change. It may be formally adopted in the future. +message TranslatedImage { + message LocalizedImage { + // String containing an URL linking to an image + // The image linked must be less than 2MB. + // If an image changes in a significant enough way that an update is required on the consumer side, the producer must update the URL to a new one. + // The URL should be a fully qualified URL that includes http:// or https://, and any special characters in the URL must be correctly escaped. See the following http://www.w3.org/Addressing/URL/4_URI_Recommentations.html for a description of how to create fully qualified URL values. + required string url = 1; + + // IANA media type as to specify the type of image to be displayed. + // The type must start with "image/" + required string media_type = 2; + + // BCP-47 language code. Can be omitted if the language is unknown or if + // no i18n is done at all for the feed. At most one translation is + // allowed to have an unspecified language tag. + optional string language = 3; + + + // The extensions namespace allows 3rd-party developers to extend the + // GTFS Realtime Specification in order to add and evaluate new features and + // modifications to the spec. + extensions 1000 to 1999; + + // The following extension IDs are reserved for private use by any organization. + extensions 9000 to 9999; + } + // At least one localized image must be provided. + repeated LocalizedImage localized_image = 1; + + // The extensions namespace allows 3rd-party developers to extend the + // GTFS Realtime Specification in order to add and evaluate new features and + // modifications to the spec. + extensions 1000 to 1999; + + // The following extension IDs are reserved for private use by any organization. + extensions 9000 to 9999; +} + +// Describes the physical path that a vehicle takes when it's not part of the (CSV) GTFS, +// such as for a detour. Shapes belong to Trips, and consist of a sequence of shape points. +// Tracing the points in order provides the path of the vehicle. Shapes do not need to intercept +// the location of Stops exactly, but all Stops on a trip should lie within a small distance of +// the shape for that trip, i.e. close to straight line segments connecting the shape points +// NOTE: This message is still experimental, and subject to change. It may be formally adopted in the future. +message Shape { + // Identifier of the shape. Must be different than any shape_id defined in the (CSV) GTFS. + // This field is required as per reference.md, but needs to be specified here optional because "Required is Forever" + // See https://developers.google.com/protocol-buffers/docs/proto#specifying_field_rules + // NOTE: This field is still experimental, and subject to change. It may be formally adopted in the future. + optional string shape_id = 1; + + // Encoded polyline representation of the shape. This polyline must contain at least two points. + // For more information about encoded polylines, see https://developers.google.com/maps/documentation/utilities/polylinealgorithm + // This field is required as per reference.md, but needs to be specified here optional because "Required is Forever" + // See https://developers.google.com/protocol-buffers/docs/proto#specifying_field_rules + // NOTE: This field is still experimental, and subject to change. It may be formally adopted in the future. + optional string encoded_polyline = 2; + + // The extensions namespace allows 3rd-party developers to extend the + // GTFS Realtime Specification in order to add and evaluate new features and + // modifications to the spec. + extensions 1000 to 1999; + + // The following extension IDs are reserved for private use by any organization. + extensions 9000 to 9999; +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..6cc132f --- /dev/null +++ b/src/main.rs @@ -0,0 +1,32 @@ +// Include the module generated from the .proto file +include!(concat!(env!("OUT_DIR"), "/transit_realtime.rs")); + +use prost::Message; + +use std::error::Error; + +#[tokio::main] +async fn main() -> Result<(), Box> { + // Denver RTD realtime vehicle positions + let url = "https://rtd.prod.acquia-sites.com/files/gtfs-rt/VehiclePosition.pb"; + + let response = reqwest::get(url).await?; + let bytes = response.bytes().await?; + + + + let feed = FeedMessage::decode(bytes.as_ref())?; + + dbg!(&feed); + for entity in feed.entity { + let vehicle = entity.vehicle.unwrap(); + let position = vehicle.position.unwrap(); + println!( + "Vehicle ID: {}, Latitude: {}, Longitude: {}", + vehicle.vehicle.unwrap().id.unwrap(), + position.latitude, + position.longitude + ); + } + Ok(()) +}