diff --git a/Cargo.lock b/Cargo.lock index 1a1c58a..84628ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -63,9 +69,20 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.101" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "atomicwrites" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ef1bb8d1b645fe38d51dfc331d720fb5fc2c94b440c76cc79c80ff265ca33e3" +dependencies = [ + "rustix 0.38.44", + "tempfile", + "windows-sys 0.52.0", +] [[package]] name = "autocfg" @@ -90,9 +107,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.19.1" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "bytes" @@ -150,9 +167,9 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "chrono" -version = "0.4.43" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ "iana-time-zone", "js-sys", @@ -164,9 +181,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.59" +version = "4.5.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5caf74d17c3aec5495110c34cc3f78644bfa89af6c8993ed4de2790e49b6499" +checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a" dependencies = [ "clap_builder", "clap_derive", @@ -174,9 +191,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.59" +version = "4.5.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "370daa45065b80218950227371916a1633217ae42b2715b2287b606dcd618e24" +checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876" dependencies = [ "anstream", "anstyle", @@ -250,9 +267,9 @@ checksum = "ffe7ed1d93f4553003e20b629abe9085e1e81b1429520f897f8f8860bc6dfc21" [[package]] name = "deranged" -version = "0.5.6" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc3dc5ad92c2e2d1c193bbbbdf2ea477cb81331de4f3103f267ca18368b988c4" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ "powerfmt", ] @@ -331,6 +348,18 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "expectorate" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cfe29c067b3dd398703f5cb05420a21c21079edfbcfa96c3ff2d9bde55cc8b3" +dependencies = [ + "atomicwrites", + "console", + "newline-converter", + "similar", +] + [[package]] name = "fastrand" version = "2.3.0" @@ -355,6 +384,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "futures" version = "0.3.32" @@ -462,7 +497,7 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "foldhash", + "foldhash 0.1.5", ] [[package]] @@ -470,6 +505,11 @@ name = "hashbrown" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] [[package]] name = "heck" @@ -584,9 +624,9 @@ checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "js-sys" -version = "0.3.85" +version = "0.3.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" +checksum = "14dc6f6450b3f6d4ed5b16327f38fed626d375a886159ca555bd7822c0c3a5a6" dependencies = [ "once_cell", "wasm-bindgen", @@ -631,9 +671,15 @@ checksum = "bfae20f6b19ad527b550c223fddc3077a547fc70cda94b9b566575423fd303ee" [[package]] name = "linux-raw-sys" -version = "0.11.0" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "log" @@ -647,6 +693,15 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +[[package]] +name = "newline-converter" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b6b097ecb1cbfed438542d16e84fd7ad9b0c76c8a65b7f9039212a3d14dc7f" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "newtype-uuid" version = "1.3.2" @@ -694,9 +749,9 @@ checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "owo-colors" -version = "4.2.3" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52" +checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" [[package]] name = "oxide-update-engine" @@ -751,6 +806,7 @@ version = "0.1.0" dependencies = [ "anyhow", "derive-where", + "expectorate", "indent_write", "indexmap", "indoc", @@ -829,16 +885,39 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "regress" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2057b2325e68a893284d1538021ab90279adac1139957ca2a74426c6f118fb48" +dependencies = [ + "hashbrown 0.16.1", + "memchr", +] + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + [[package]] name = "rustix" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ "bitflags", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.12.1", "windows-sys 0.61.2", ] @@ -878,6 +957,10 @@ name = "semver" version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +dependencies = [ + "serde", + "serde_core", +] [[package]] name = "serde" @@ -933,12 +1016,30 @@ dependencies = [ "zmij", ] +[[package]] +name = "serde_tokenstream" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c49585c52c01f13c5c2ebb333f14f6885d76daa768d8a037d28017ec538c69" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "syn", +] + [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "similar" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" + [[package]] name = "slab" version = "0.4.12" @@ -1006,9 +1107,9 @@ checksum = "7f3fece30b2dc06d65ecbca97b602db15bf75f932711d60cc604534f1f8b7a03" [[package]] name = "syn" -version = "2.0.116" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3df424c70518695237746f84cede799c9c58fcb37450d7b23716568cc8bc69cb" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -1023,14 +1124,14 @@ checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" [[package]] name = "tempfile" -version = "3.25.0" +version = "3.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1" +checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0" dependencies = [ "fastrand", "getrandom", "once_cell", - "rustix", + "rustix 1.1.4", "windows-sys 0.61.2", ] @@ -1043,6 +1144,26 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thread_local" version = "1.1.9" @@ -1116,12 +1237,79 @@ dependencies = [ "tokio", ] +[[package]] +name = "typify" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b715573a376585888b742ead9be5f4826105e622169180662e2c81bed4a149c3" +dependencies = [ + "typify-impl", + "typify-macro", +] + +[[package]] +name = "typify-example" +version = "0.0.0" +dependencies = [ + "anyhow", + "expectorate", + "oxide-update-engine-types", + "prettyplease", + "schemars", + "serde_json", + "syn", + "typify", +] + +[[package]] +name = "typify-impl" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2fd0d27608a466d063d23b97cf2d26c25d838f01b4f7d5ff406a7446f16b6e3" +dependencies = [ + "heck", + "log", + "proc-macro2", + "quote", + "regress", + "schemars", + "semver", + "serde", + "serde_json", + "syn", + "thiserror", + "unicode-ident", +] + +[[package]] +name = "typify-macro" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd04bb1207cd4e250941cc1641f4c4815f7eaa2145f45c09dd49cb0a3691710a" +dependencies = [ + "proc-macro2", + "quote", + "schemars", + "semver", + "serde", + "serde_json", + "serde_tokenstream", + "syn", + "typify-impl", +] + [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + [[package]] name = "unicode-width" version = "0.2.2" @@ -1172,9 +1360,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.108" +version = "0.2.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" +checksum = "60722a937f594b7fde9adb894d7c092fc1bb6612897c46368d18e7a20208eff2" dependencies = [ "cfg-if", "once_cell", @@ -1185,9 +1373,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.108" +version = "0.2.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" +checksum = "0fac8c6395094b6b91c4af293f4c79371c163f9a6f56184d2c9a85f5a95f3950" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1195,9 +1383,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.108" +version = "0.2.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" +checksum = "ab3fabce6159dc20728033842636887e4877688ae94382766e00b180abac9d60" dependencies = [ "bumpalo", "proc-macro2", @@ -1208,9 +1396,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.108" +version = "0.2.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" +checksum = "de0e091bdb824da87dc01d967388880d017a0a9bc4f3bdc0d86ee9f9336e3bb5" dependencies = [ "unicode-ident", ] @@ -1318,6 +1506,15 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.59.0" diff --git a/Cargo.toml b/Cargo.toml index 6bcdc1f..0df1372 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ resolver = "3" members = [ "crates/*", "e2e-example", + "typify-example", ] [workspace.package] @@ -25,6 +26,7 @@ chrono = { version = "0.4", features = ["serde"] } clap = { version = "4", features = ["derive"] } debug-ignore = "1" derive-where = "1" +expectorate = "1" futures = "0.3" indent_write = "2" indexmap = { version = "2", features = ["serde"] } @@ -39,6 +41,7 @@ oxide-update-engine-test-utils = { version = "0.1.0", path = "crates/oxide-updat oxide-update-engine-types = { version = "0.1.0", path = "crates/oxide-update-engine-types" } owo-colors = "4" petgraph = { version = "0.8", default-features = false, features = ["graphmap", "std"] } +prettyplease = "0.2" schemars = { version = "0.8", features = ["uuid1"] } serde = { version = "1", features = ["derive"] } serde_json = "1" @@ -46,8 +49,10 @@ slog = "2" slog-async = "2" slog-term = "2" supports-color = "3" +syn = { version = "2", features = ["full"] } swrite = "0.1" tokio = { version = "1", features = ["macros", "sync", "time", "rt-multi-thread"] } tokio-stream = "0.1" +typify = "0.6.1" unicode-width = "0.2" uuid = { version = "1", features = ["v4", "serde"] } diff --git a/crates/oxide-update-engine-types/Cargo.toml b/crates/oxide-update-engine-types/Cargo.toml index b23ec48..99007f0 100644 --- a/crates/oxide-update-engine-types/Cargo.toml +++ b/crates/oxide-update-engine-types/Cargo.toml @@ -42,8 +42,10 @@ pre-release-replacements = [ [dev-dependencies] anyhow.workspace = true +expectorate.workspace = true indexmap.workspace = true indoc.workspace = true +schemars = { workspace = true } oxide-update-engine-test-utils.workspace = true petgraph.workspace = true serde_json.workspace = true diff --git a/crates/oxide-update-engine-types/src/events.rs b/crates/oxide-update-engine-types/src/events.rs index db1eea0..f320f62 100644 --- a/crates/oxide-update-engine-types/src/events.rs +++ b/crates/oxide-update-engine-types/src/events.rs @@ -44,9 +44,29 @@ impl schemars::JsonSchema for ExecutionUuidKind { } fn json_schema( - generator: &mut schemars::r#gen::SchemaGenerator, + _: &mut schemars::r#gen::SchemaGenerator, ) -> schemars::schema::Schema { - uuid::Uuid::json_schema(generator) + use crate::schema::{EVENTS_MODULE, rust_type_for_events}; + + // Produce a UUID schema with x-rust-type so that + // newtype-uuid's lifting mechanism produces a + // TypedUuid schema with path + // "oxide_update_engine_types::events::ExecutionUuid" (via + // the alias() method on TypedUuidKind). + schemars::schema::SchemaObject { + instance_type: Some(schemars::schema::InstanceType::String.into()), + format: Some("uuid".to_owned()), + extensions: [( + "x-rust-type".to_owned(), + rust_type_for_events(&format!( + "{EVENTS_MODULE}::ExecutionUuidKind" + )), + )] + .into_iter() + .collect(), + ..Default::default() + } + .into() } } @@ -98,13 +118,8 @@ impl Event { } #[derive(Deserialize, Serialize)] -#[cfg_attr(feature = "schemars08", derive(schemars::JsonSchema))] #[derive_where(Clone, Debug, Eq, PartialEq)] #[serde(bound = "", rename_all = "snake_case")] -#[cfg_attr( - feature = "schemars08", - schemars(rename = "StepEventFor{S}", bound = "S: JsonSchemaEngineSpec",) -)] pub struct StepEvent { /// The specification that this event belongs to. /// @@ -137,6 +152,79 @@ pub struct StepEvent { pub kind: StepEventKind, } +#[cfg(feature = "schemars08")] +impl schemars::JsonSchema for StepEvent { + fn schema_name() -> String { + format!("StepEventFor{}", S::schema_name()) + } + + fn json_schema( + generator: &mut schemars::r#gen::SchemaGenerator, + ) -> schemars::schema::Schema { + use crate::schema::with_description; + use schemars::schema::{ObjectValidation, SchemaObject}; + + let mut obj = ObjectValidation::default(); + obj.properties.insert( + "spec".to_owned(), + with_description( + generator.subschema_for::(), + "The specification that this event belongs to.", + ), + ); + obj.properties.insert( + "execution_id".to_owned(), + with_description( + generator.subschema_for::(), + "The execution ID.", + ), + ); + obj.properties.insert( + "event_index".to_owned(), + with_description( + generator.subschema_for::(), + "A monotonically increasing index for this \ + `StepEvent`.", + ), + ); + obj.properties.insert( + "total_elapsed".to_owned(), + with_description( + generator.subschema_for::(), + "Total time elapsed since the start of execution.", + ), + ); + obj.properties.insert( + "data".to_owned(), + with_description( + generator.subschema_for::>(), + "The kind of event this is.", + ), + ); + obj.required = + ["spec", "execution_id", "event_index", "total_elapsed", "data"] + .into_iter() + .map(String::from) + .collect(); + + let mut extensions = serde_json::Map::new(); + if let Some(info) = S::rust_type_info() { + extensions.insert( + "x-rust-type".to_owned(), + crate::schema::rust_type_for_generic(&info, "StepEvent"), + ); + } + + SchemaObject { + instance_type: Some(schemars::schema::InstanceType::Object.into()), + object: Some(Box::new(obj)), + extensions: extensions.into_iter().collect(), + ..Default::default() + } + .into() + } +} + impl StepEvent { /// Returns a progress event associated with this step event, if any. /// @@ -1040,16 +1128,8 @@ impl StepOutcome { } #[derive(Deserialize, Serialize)] -#[cfg_attr(feature = "schemars08", derive(schemars::JsonSchema))] #[derive_where(Clone, Debug, Eq, PartialEq)] #[serde(bound = "", rename_all = "snake_case")] -#[cfg_attr( - feature = "schemars08", - schemars( - rename = "ProgressEventFor{S}", - bound = "S: JsonSchemaEngineSpec", - ) -)] pub struct ProgressEvent { /// The specification that this event belongs to. /// @@ -1071,6 +1151,70 @@ pub struct ProgressEvent { pub kind: ProgressEventKind, } +#[cfg(feature = "schemars08")] +impl schemars::JsonSchema for ProgressEvent { + fn schema_name() -> String { + format!("ProgressEventFor{}", S::schema_name()) + } + + fn json_schema( + generator: &mut schemars::r#gen::SchemaGenerator, + ) -> schemars::schema::Schema { + use crate::schema::with_description; + use schemars::schema::{ObjectValidation, SchemaObject}; + + let mut obj = ObjectValidation::default(); + obj.properties.insert( + "spec".to_owned(), + with_description( + generator.subschema_for::(), + "The specification that this event belongs to.", + ), + ); + obj.properties.insert( + "execution_id".to_owned(), + with_description( + generator.subschema_for::(), + "The execution ID.", + ), + ); + obj.properties.insert( + "total_elapsed".to_owned(), + with_description( + generator.subschema_for::(), + "Total time elapsed since the start of execution.", + ), + ); + obj.properties.insert( + "data".to_owned(), + with_description( + generator.subschema_for::>(), + "The kind of event this is.", + ), + ); + obj.required = ["spec", "execution_id", "total_elapsed", "data"] + .into_iter() + .map(String::from) + .collect(); + + let mut extensions = serde_json::Map::new(); + if let Some(info) = S::rust_type_info() { + extensions.insert( + "x-rust-type".to_owned(), + crate::schema::rust_type_for_generic(&info, "ProgressEvent"), + ); + } + + SchemaObject { + instance_type: Some(schemars::schema::InstanceType::Object.into()), + object: Some(Box::new(obj)), + extensions: extensions.into_iter().collect(), + ..Default::default() + } + .into() + } +} + impl ProgressEvent { /// Converts a generic version into self. /// @@ -1564,7 +1708,6 @@ impl StepInfoWithMetadata { /// subsequent events; that can happen e.g. if a fetch happens from multiple /// peers within a single attempt. #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] -#[cfg_attr(feature = "schemars08", derive(schemars::JsonSchema))] #[serde(rename_all = "snake_case")] pub struct ProgressCounter { /// The current progress. @@ -1577,6 +1720,66 @@ pub struct ProgressCounter { pub units: ProgressUnits, } +#[cfg(feature = "schemars08")] +impl schemars::JsonSchema for ProgressCounter { + fn schema_name() -> String { + "ProgressCounter".to_owned() + } + + fn json_schema( + generator: &mut schemars::r#gen::SchemaGenerator, + ) -> schemars::schema::Schema { + use crate::schema::{ + EVENTS_MODULE, rust_type_for_events, with_description, + }; + use schemars::schema::{ObjectValidation, SchemaObject}; + + let mut obj = ObjectValidation::default(); + obj.properties.insert( + "current".to_owned(), + with_description( + generator.subschema_for::(), + "The current progress.", + ), + ); + obj.properties.insert( + "total".to_owned(), + with_description( + generator.subschema_for::>(), + "The total progress.", + ), + ); + obj.properties.insert( + "units".to_owned(), + with_description( + generator.subschema_for::(), + "Progress units.", + ), + ); + obj.required = + ["current", "units"].into_iter().map(String::from).collect(); + + SchemaObject { + metadata: Some(Box::new(schemars::schema::Metadata { + description: Some("Current progress.".to_owned()), + ..Default::default() + })), + instance_type: Some(schemars::schema::InstanceType::Object.into()), + object: Some(Box::new(obj)), + extensions: [( + "x-rust-type".to_owned(), + rust_type_for_events(&format!( + "{EVENTS_MODULE}::ProgressCounter" + )), + )] + .into_iter() + .collect(), + ..Default::default() + } + .into() + } +} + impl ProgressCounter { /// Creates a new `ProgressCounter` with current and total values. #[inline] @@ -1596,10 +1799,44 @@ impl ProgressCounter { } #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] -#[cfg_attr(feature = "schemars08", derive(schemars::JsonSchema))] #[serde(transparent)] pub struct ProgressUnits(pub Cow<'static, str>); +#[cfg(feature = "schemars08")] +impl schemars::JsonSchema for ProgressUnits { + fn schema_name() -> String { + "ProgressUnits".to_owned() + } + + fn json_schema( + generator: &mut schemars::r#gen::SchemaGenerator, + ) -> schemars::schema::Schema { + use crate::schema::{EVENTS_MODULE, rust_type_for_events}; + + // ProgressUnits is a transparent wrapper around a string. + // Delegate to String's schema and add x-rust-type. + let mut schema = match generator.subschema_for::() { + schemars::schema::Schema::Object(obj) => obj, + // String always produces an Object schema with + // schemars 0.8. If this changes, we need to handle + // it explicitly. + other => { + debug_assert!( + false, + "expected String to produce an Object \ + schema, got: {other:?}", + ); + return other; + } + }; + schema.extensions.insert( + "x-rust-type".to_owned(), + rust_type_for_events(&format!("{EVENTS_MODULE}::ProgressUnits")), + ); + schema.into() + } +} + impl ProgressUnits { /// Creates a new `ProgressUnits`. pub fn new(s: impl Into>) -> Self { @@ -1728,12 +1965,7 @@ impl StepProgress { /// they show up as nested events. #[derive_where(Clone, Debug, Default, Eq, PartialEq)] #[derive(Deserialize, Serialize)] -#[cfg_attr(feature = "schemars08", derive(schemars::JsonSchema))] #[serde(bound = "", rename_all = "snake_case")] -#[cfg_attr( - feature = "schemars08", - schemars(rename = "EventReportFor{S}", bound = "S: JsonSchemaEngineSpec",) -)] pub struct EventReport { /// A list of step events. /// @@ -1760,6 +1992,81 @@ pub struct EventReport { pub last_seen: Option, } +#[cfg(feature = "schemars08")] +impl schemars::JsonSchema for EventReport { + fn schema_name() -> String { + format!("EventReportFor{}", S::schema_name()) + } + + fn json_schema( + generator: &mut schemars::r#gen::SchemaGenerator, + ) -> schemars::schema::Schema { + use crate::schema::with_description; + use schemars::schema::{ObjectValidation, SchemaObject}; + + let mut obj = ObjectValidation::default(); + obj.properties.insert( + "step_events".to_owned(), + with_description( + generator.subschema_for::>>(), + "A list of step events.", + ), + ); + obj.properties.insert( + "progress_events".to_owned(), + with_description( + generator.subschema_for::>>(), + "A list of progress events, or whether we're \ + currently waiting for a progress event.", + ), + ); + obj.properties.insert( + "root_execution_id".to_owned(), + with_description( + generator.subschema_for::>(), + "The root execution ID for this report.", + ), + ); + obj.properties.insert( + "last_seen".to_owned(), + with_description( + generator.subschema_for::>(), + "The last event seen.", + ), + ); + obj.required = ["step_events", "progress_events"] + .into_iter() + .map(String::from) + .collect(); + + let mut extensions = serde_json::Map::new(); + if let Some(info) = S::rust_type_info() { + extensions.insert( + "x-rust-type".to_owned(), + crate::schema::rust_type_for_generic(&info, "EventReport"), + ); + } + + SchemaObject { + metadata: Some(Box::new(schemars::schema::Metadata { + description: Some( + "An oxide-update-engine event report.\ + \n\nRemote reports can be passed into a \ + `StepContext`, in which case they show up as \ + nested events." + .to_owned(), + ), + ..Default::default() + })), + instance_type: Some(schemars::schema::InstanceType::Object.into()), + object: Some(Box::new(obj)), + extensions: extensions.into_iter().collect(), + ..Default::default() + } + .into() + } +} + impl EventReport { /// Converts a generic version into self. /// @@ -2106,4 +2413,262 @@ mod tests { assert_eq!(expected, actual, "input matches actual output"); } } + + // --- Schema tests (schemars08 feature) --- + + #[cfg(feature = "schemars08")] + mod schema_tests { + use super::*; + use crate::schema::RustTypeInfo; + use schemars::{JsonSchema, r#gen::SchemaGenerator, schema::Schema}; + + /// Extract the x-rust-type extension from a schema, if + /// present. + fn get_rust_type_ext(schema: &Schema) -> Option<&serde_json::Value> { + match schema { + Schema::Object(obj) => obj.extensions.get("x-rust-type"), + Schema::Bool(_) => None, + } + } + + /// Assert that x-rust-type has the expected crate, version, + /// and path. + fn assert_rust_type_ext( + x_rust_type: &serde_json::Value, + expected_crate: &str, + expected_version: &str, + expected_path: &str, + ) { + assert_eq!( + x_rust_type.get("crate").and_then(|v| v.as_str()), + Some(expected_crate), + "x-rust-type crate" + ); + assert_eq!( + x_rust_type.get("version").and_then(|v| v.as_str()), + Some(expected_version), + "x-rust-type version" + ); + assert_eq!( + x_rust_type.get("path").and_then(|v| v.as_str()), + Some(expected_path), + "x-rust-type path" + ); + } + + // -- Non-generic types -- + + #[test] + fn execution_uuid_kind_rust_type() { + let mut generator = SchemaGenerator::default(); + let schema = ExecutionUuidKind::json_schema(&mut generator); + let xrt = get_rust_type_ext(&schema).expect("x-rust-type present"); + assert_rust_type_ext( + xrt, + "oxide-update-engine-types", + env!("CARGO_PKG_VERSION"), + "oxide_update_engine_types::events\ + ::ExecutionUuidKind", + ); + } + + #[test] + fn execution_uuid_lifted_rust_type() { + // The TypedUuid schema should + // lift the x-rust-type with the alias + // "ExecutionUuid". + let mut generator = SchemaGenerator::default(); + let schema = ExecutionUuid::json_schema(&mut generator); + let xrt = get_rust_type_ext(&schema) + .expect("x-rust-type present on ExecutionUuid"); + assert_rust_type_ext( + xrt, + "oxide-update-engine-types", + env!("CARGO_PKG_VERSION"), + "oxide_update_engine_types::events\ + ::ExecutionUuid", + ); + } + + // -- Full schema snapshot (covers all types transitively) -- + + #[test] + fn event_report_generic_spec_schema() { + let schema = schemars::schema_for!(EventReport); + let json = serde_json::to_string_pretty(&schema) + .expect("serialized schema"); + expectorate::assert_contents( + "tests/output/event_report_generic_spec_schema.json", + &json, + ); + } + + // -- Generic types with a spec that returns None for + // rust_type_info -- + + impl schemars::JsonSchema for super::TestSpec { + fn schema_name() -> String { + "TestSpec".to_owned() + } + + fn json_schema(_: &mut SchemaGenerator) -> Schema { + Schema::Bool(true) + } + } + + #[test] + fn step_event_no_rust_type_without_info() { + let mut generator = SchemaGenerator::default(); + let schema = + StepEvent::::json_schema(&mut generator); + assert!( + get_rust_type_ext(&schema).is_none(), + "no x-rust-type when spec returns None" + ); + } + + #[test] + fn progress_event_no_rust_type_without_info() { + let mut generator = SchemaGenerator::default(); + let schema = + ProgressEvent::::json_schema(&mut generator); + assert!( + get_rust_type_ext(&schema).is_none(), + "no x-rust-type when spec returns None" + ); + } + + #[test] + fn event_report_no_rust_type_without_info() { + let mut generator = SchemaGenerator::default(); + let schema = + EventReport::::json_schema(&mut generator); + assert!( + get_rust_type_ext(&schema).is_none(), + "no x-rust-type when spec returns None" + ); + } + + // -- Generic types with a spec whose rust_type_info points + // to an external crate -- + + /// A spec that returns `RustTypeInfo` pointing to a + /// hypothetical external crate, simulating a user-defined + /// spec in a downstream consumer. + enum TestSpecWithInfo {} + + impl crate::spec::EngineSpec for TestSpecWithInfo { + fn spec_name() -> String { + "TestSpecWithInfo".to_owned() + } + + type Component = serde_json::Value; + type StepId = serde_json::Value; + type StepMetadata = serde_json::Value; + type ProgressMetadata = serde_json::Value; + type CompletionMetadata = serde_json::Value; + type SkippedMetadata = serde_json::Value; + type Error = anyhow::Error; + + fn rust_type_info() -> Option { + Some(RustTypeInfo { + crate_name: "my-external-crate", + version: "1.2.3", + path: "my_external_crate::MySpec", + }) + } + } + + impl JsonSchema for TestSpecWithInfo { + fn schema_name() -> String { + "TestSpecWithInfo".to_owned() + } + + fn json_schema(_: &mut SchemaGenerator) -> Schema { + Schema::Bool(true) + } + } + + /// Assert that the outer type in an x-rust-type extension + /// points to `oxide-update-engine-types`, while the + /// parameter points to the spec's crate. + fn assert_external_spec_rust_type( + x_rust_type: &serde_json::Value, + expected_outer_path: &str, + expected_param_crate: &str, + expected_param_version: &str, + expected_param_path: &str, + ) { + // Outer type: always oxide-update-engine-types. + assert_rust_type_ext( + x_rust_type, + "oxide-update-engine-types", + env!("CARGO_PKG_VERSION"), + expected_outer_path, + ); + + // Parameter: the spec's crate. + let params = x_rust_type + .get("parameters") + .and_then(|v| v.as_array()) + .expect("parameters array present"); + assert_eq!(params.len(), 1, "exactly one parameter"); + let param_xrt = params[0] + .get("x-rust-type") + .expect("parameter x-rust-type present"); + assert_rust_type_ext( + param_xrt, + expected_param_crate, + expected_param_version, + expected_param_path, + ); + } + + #[test] + fn step_event_external_spec_rust_type() { + let mut generator = SchemaGenerator::default(); + let schema = + StepEvent::::json_schema(&mut generator); + let xrt = get_rust_type_ext(&schema).expect("x-rust-type present"); + assert_external_spec_rust_type( + xrt, + "oxide_update_engine_types::events::StepEvent", + "my-external-crate", + "1.2.3", + "my_external_crate::MySpec", + ); + } + + #[test] + fn progress_event_external_spec_rust_type() { + let mut generator = SchemaGenerator::default(); + let schema = + ProgressEvent::::json_schema(&mut generator); + let xrt = get_rust_type_ext(&schema).expect("x-rust-type present"); + assert_external_spec_rust_type( + xrt, + "oxide_update_engine_types::events\ + ::ProgressEvent", + "my-external-crate", + "1.2.3", + "my_external_crate::MySpec", + ); + } + + #[test] + fn event_report_external_spec_rust_type() { + let mut generator = SchemaGenerator::default(); + let schema = + EventReport::::json_schema(&mut generator); + let xrt = get_rust_type_ext(&schema).expect("x-rust-type present"); + assert_external_spec_rust_type( + xrt, + "oxide_update_engine_types::events\ + ::EventReport", + "my-external-crate", + "1.2.3", + "my_external_crate::MySpec", + ); + } + } } diff --git a/crates/oxide-update-engine-types/src/lib.rs b/crates/oxide-update-engine-types/src/lib.rs index 5d40b5c..b7e903f 100644 --- a/crates/oxide-update-engine-types/src/lib.rs +++ b/crates/oxide-update-engine-types/src/lib.rs @@ -18,4 +18,5 @@ pub mod buffer; pub mod errors; pub mod events; mod macros; +pub mod schema; pub mod spec; diff --git a/crates/oxide-update-engine-types/src/schema.rs b/crates/oxide-update-engine-types/src/schema.rs new file mode 100644 index 0000000..02b001e --- /dev/null +++ b/crates/oxide-update-engine-types/src/schema.rs @@ -0,0 +1,160 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +//! Helpers for building `x-rust-type` JSON Schema extensions. +//! +//! The `x-rust-type` extension tells code generators like typify and +//! progenitor to use an existing Rust type rather than generating a +//! new one. This module provides the shared constants and builder +//! used by the manual `JsonSchema` implementations throughout this +//! crate. + +/// Information for the `x-rust-type` JSON Schema extension. +/// +/// When an [`EngineSpec`](crate::spec::EngineSpec) provides this, +/// generic types parameterized by that spec will include the +/// `x-rust-type` extension in their JSON Schema. +/// +/// This describes only the **spec type** (the generic parameter). +/// The outer types (`StepEvent`, `ProgressEvent`, `EventReport`) +/// always live in `oxide-update-engine-types` and use the module +/// constants directly. +#[derive(Clone, Debug)] +pub struct RustTypeInfo { + /// The crate that defines the spec type (e.g. + /// `"oxide-update-engine-types"` for `GenericSpec`, or + /// `"my-crate"` for a user-defined spec). + pub crate_name: &'static str, + /// The version requirement for the spec's crate (e.g. `"*"`). + pub version: &'static str, + /// The full path to the spec type (e.g. + /// `"oxide_update_engine_types::spec::GenericSpec"` or + /// `"my_crate::MySpec"`). + pub path: &'static str, +} + +/// Crate name used in `x-rust-type` for types in this crate. +pub(crate) const CRATE_NAME: &str = "oxide-update-engine-types"; + +/// Version requirement used in `x-rust-type` for types in this +/// crate. +pub(crate) const VERSION: &str = env!("CARGO_PKG_VERSION"); + +/// Module path for `events` types in this crate. +#[cfg(feature = "schemars08")] +pub(crate) const EVENTS_MODULE: &str = "oxide_update_engine_types::events"; + +/// Full path to `GenericSpec` in this crate. +pub(crate) const GENERIC_SPEC_PATH: &str = + "oxide_update_engine_types::spec::GenericSpec"; + +/// Attaches a description to a schema, mirroring what the schemars +/// derive does for doc comments on struct fields. +/// +/// If the schema is a `$ref`, it is wrapped in `allOf` so that the +/// description can sit alongside the reference (JSON Schema does not +/// allow sibling keywords next to `$ref` in draft-07). +#[cfg(feature = "schemars08")] +pub(crate) fn with_description( + schema: schemars::schema::Schema, + description: &str, +) -> schemars::schema::Schema { + use schemars::schema::{Metadata, Schema, SchemaObject}; + + match schema { + Schema::Object(obj) if obj.reference.is_some() => { + // Wrap `$ref` in allOf so the description is + // preserved. + SchemaObject { + metadata: Some(Box::new(Metadata { + description: Some(description.to_owned()), + ..Default::default() + })), + subschemas: Some(Box::new( + schemars::schema::SubschemaValidation { + all_of: Some(vec![Schema::Object(obj)]), + ..Default::default() + }, + )), + ..Default::default() + } + .into() + } + Schema::Object(mut obj) => { + let metadata = obj.metadata.get_or_insert_with(Default::default); + metadata.description = Some(description.to_owned()); + obj.into() + } + // Schema::Bool (e.g. `true` for unconstrained types like + // serde_json::Value) cannot carry metadata directly. + // Wrap it in allOf so we can attach the description, + // mirroring the $ref case above. + other => SchemaObject { + metadata: Some(Box::new(Metadata { + description: Some(description.to_owned()), + ..Default::default() + })), + subschemas: Some(Box::new(schemars::schema::SubschemaValidation { + all_of: Some(vec![other]), + ..Default::default() + })), + ..Default::default() + } + .into(), + } +} + +/// Builds the `x-rust-type` extension value for a type in the +/// `events` module of this crate. +#[cfg(feature = "schemars08")] +pub(crate) fn rust_type_for_events(type_path: &str) -> serde_json::Value { + serde_json::json!({ + "crate": CRATE_NAME, + "version": VERSION, + "path": type_path, + }) +} + +/// Builds the `x-rust-type` extension value for a generic type +/// parameterized by a spec (e.g. `StepEvent`). +/// +/// The outer type (e.g. `StepEvent`) always lives in +/// `oxide-update-engine-types`, so the top-level crate/version/path +/// come from the module constants. The `parameters` array contains +/// an inline schema with its own `x-rust-type` pointing to the +/// spec type, which may live in a different crate. +#[cfg(feature = "schemars08")] +pub(crate) fn rust_type_for_generic( + info: &RustTypeInfo, + type_name: &str, +) -> serde_json::Value { + serde_json::json!({ + "crate": CRATE_NAME, + "version": VERSION, + "path": format!( + "{}::{}", + EVENTS_MODULE, type_name, + ), + "parameters": [ + { + "x-rust-type": { + "crate": info.crate_name, + "version": info.version, + "path": info.path, + } + } + ], + }) +} + +// NOTE: We only add `x-rust-type` to the outermost types such as `EventReport`. +// Ideally, `StepEventKind` and other inner types below would also carry +// `x-rust-type` in their schemas. However, schemars 0.8 does not provide a way +// to intercept or transform a derived schema, so adding `x-rust-type` requires +// a fully manual `JsonSchema` impl. Manual impls are quite fragile, and changes +// to the shape of the type can silently break the schema. +// +// In practice, this is acceptable because these inner types are always accessed +// through the top-level types which *do* carry `x-rust-type`, so typify +// replaces the entire type tree. diff --git a/crates/oxide-update-engine-types/src/spec.rs b/crates/oxide-update-engine-types/src/spec.rs index a5e219f..ca3e53d 100644 --- a/crates/oxide-update-engine-types/src/spec.rs +++ b/crates/oxide-update-engine-types/src/spec.rs @@ -2,6 +2,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. +use crate::schema::RustTypeInfo; use anyhow::anyhow; use indent_write::fmt::IndentWriter; use serde::{Serialize, de::DeserializeOwned}; @@ -88,8 +89,30 @@ pub trait EngineSpec: Send + 'static { /// Both can be converted to a dynamic `Error`, though. We use /// `AsError` to abstract over both sorts of errors. type Error: AsError + fmt::Debug + Send + Sync; + + /// Information for the `x-rust-type` JSON Schema extension. + /// + /// When this returns `Some`, generic types parameterized by this + /// spec will include the `x-rust-type` extension in their JSON + /// Schema, enabling automatic type replacement in typify and + /// progenitor. + fn rust_type_info() -> Option { + None + } } +/// A trait that requires and provides JSON Schema information for an +/// [`EngineSpec`]. +/// +/// This trait has a blanket implementation. To implement this trait, +/// implement [`JsonSchema`](schemars::JsonSchema) for: +/// +/// * the `EngineSpec` type itself +/// * all associated types other than the error type +/// +/// It is also recommended that you add a +/// [`rust_type_info`](EngineSpec::rust_type_info) method to your `EngineSpec` +/// implementation to enable automatic replacement in typify and progenitor. #[cfg(feature = "schemars08")] pub trait JsonSchemaEngineSpec: EngineSpec< @@ -149,6 +172,14 @@ impl EngineSpec for GenericSpec { type CompletionMetadata = serde_json::Value; type SkippedMetadata = serde_json::Value; type Error = SerializableError; + + fn rust_type_info() -> Option { + Some(RustTypeInfo { + crate_name: crate::schema::CRATE_NAME, + version: crate::schema::VERSION, + path: crate::schema::GENERIC_SPEC_PATH, + }) + } } /// A serializable representation of an error chain. diff --git a/crates/oxide-update-engine-types/tests/buffer.rs b/crates/oxide-update-engine-types/tests/buffer.rs index 8b29c38..0421860 100644 --- a/crates/oxide-update-engine-types/tests/buffer.rs +++ b/crates/oxide-update-engine-types/tests/buffer.rs @@ -720,8 +720,8 @@ fn step_keys_impl( } #[derive(Copy, Clone, Debug)] -#[allow(unused)] enum WithDeltas { + #[expect(unused)] Yes, No, Both, diff --git a/crates/oxide-update-engine-types/tests/output/event_report_generic_spec_schema.json b/crates/oxide-update-engine-types/tests/output/event_report_generic_spec_schema.json new file mode 100644 index 0000000..9563fbf --- /dev/null +++ b/crates/oxide-update-engine-types/tests/output/event_report_generic_spec_schema.json @@ -0,0 +1,1077 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "EventReportForGenericSpec", + "description": "An oxide-update-engine event report.\n\nRemote reports can be passed into a `StepContext`, in which case they show up as nested events.", + "type": "object", + "required": [ + "progress_events", + "step_events" + ], + "properties": { + "last_seen": { + "description": "The last event seen.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "progress_events": { + "description": "A list of progress events, or whether we're currently waiting for a progress event.", + "type": "array", + "items": { + "$ref": "#/definitions/ProgressEventForGenericSpec" + } + }, + "root_execution_id": { + "description": "The root execution ID for this report.", + "anyOf": [ + { + "$ref": "#/definitions/ExecutionUuid" + }, + { + "type": "null" + } + ] + }, + "step_events": { + "description": "A list of step events.", + "type": "array", + "items": { + "$ref": "#/definitions/StepEventForGenericSpec" + } + } + }, + "x-rust-type": { + "crate": "oxide-update-engine-types", + "parameters": [ + { + "x-rust-type": { + "crate": "oxide-update-engine-types", + "path": "oxide_update_engine_types::spec::GenericSpec", + "version": "0.1.0" + } + } + ], + "path": "oxide_update_engine_types::events::EventReport", + "version": "0.1.0" + }, + "definitions": { + "Duration": { + "type": "object", + "required": [ + "nanos", + "secs" + ], + "properties": { + "nanos": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "secs": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + } + }, + "ExecutionUuid": { + "type": "string", + "format": "uuid", + "x-rust-type": { + "crate": "oxide-update-engine-types", + "path": "oxide_update_engine_types::events::ExecutionUuid", + "version": "0.1.0" + } + }, + "ProgressCounter": { + "description": "Current progress.", + "type": "object", + "required": [ + "current", + "units" + ], + "properties": { + "current": { + "description": "The current progress.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "total": { + "description": "The total progress.", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "units": { + "description": "Progress units.", + "allOf": [ + { + "$ref": "#/definitions/ProgressUnits" + } + ] + } + }, + "x-rust-type": { + "crate": "oxide-update-engine-types", + "path": "oxide_update_engine_types::events::ProgressCounter", + "version": "0.1.0" + } + }, + "ProgressEventForGenericSpec": { + "type": "object", + "required": [ + "data", + "execution_id", + "spec", + "total_elapsed" + ], + "properties": { + "data": { + "description": "The kind of event this is.", + "allOf": [ + { + "$ref": "#/definitions/ProgressEventKindForGenericSpec" + } + ] + }, + "execution_id": { + "description": "The execution ID.", + "allOf": [ + { + "$ref": "#/definitions/ExecutionUuid" + } + ] + }, + "spec": { + "description": "The specification that this event belongs to.", + "type": "string" + }, + "total_elapsed": { + "description": "Total time elapsed since the start of execution.", + "allOf": [ + { + "$ref": "#/definitions/Duration" + } + ] + } + }, + "x-rust-type": { + "crate": "oxide-update-engine-types", + "parameters": [ + { + "x-rust-type": { + "crate": "oxide-update-engine-types", + "path": "oxide_update_engine_types::spec::GenericSpec", + "version": "0.1.0" + } + } + ], + "path": "oxide_update_engine_types::events::ProgressEvent", + "version": "0.1.0" + } + }, + "ProgressEventKindForGenericSpec": { + "oneOf": [ + { + "description": "The update engine is waiting for a progress message.\n\nThe update engine sends this message immediately after a [`StepEvent`] corresponding to a new step.", + "type": "object", + "required": [ + "attempt", + "attempt_elapsed", + "kind", + "step", + "step_elapsed" + ], + "properties": { + "attempt": { + "description": "The attempt number currently being executed.", + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "attempt_elapsed": { + "description": "Total time elapsed since the start of the attempt.", + "allOf": [ + { + "$ref": "#/definitions/Duration" + } + ] + }, + "kind": { + "type": "string", + "enum": [ + "waiting_for_progress" + ] + }, + "step": { + "description": "Information about the step.", + "allOf": [ + { + "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" + } + ] + }, + "step_elapsed": { + "description": "Total time elapsed since the start of the step. Includes prior attempts.", + "allOf": [ + { + "$ref": "#/definitions/Duration" + } + ] + } + } + }, + { + "type": "object", + "required": [ + "attempt", + "attempt_elapsed", + "kind", + "metadata", + "step", + "step_elapsed" + ], + "properties": { + "attempt": { + "description": "The attempt number currently being executed.", + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "attempt_elapsed": { + "description": "Total time elapsed since the start of the attempt.", + "allOf": [ + { + "$ref": "#/definitions/Duration" + } + ] + }, + "kind": { + "type": "string", + "enum": [ + "progress" + ] + }, + "metadata": { + "description": "Metadata that was returned with progress." + }, + "progress": { + "description": "Current progress.", + "anyOf": [ + { + "$ref": "#/definitions/ProgressCounter" + }, + { + "type": "null" + } + ] + }, + "step": { + "description": "Information about the step.", + "allOf": [ + { + "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" + } + ] + }, + "step_elapsed": { + "description": "Total time elapsed since the start of the step. Includes prior attempts.", + "allOf": [ + { + "$ref": "#/definitions/Duration" + } + ] + } + } + }, + { + "type": "object", + "required": [ + "attempt", + "attempt_elapsed", + "event", + "kind", + "step", + "step_elapsed" + ], + "properties": { + "attempt": { + "description": "The attempt number currently being executed.", + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "attempt_elapsed": { + "description": "The time it took for this attempt to complete.", + "allOf": [ + { + "$ref": "#/definitions/Duration" + } + ] + }, + "event": { + "description": "The event that occurred.", + "allOf": [ + { + "$ref": "#/definitions/ProgressEventForGenericSpec" + } + ] + }, + "kind": { + "type": "string", + "enum": [ + "nested" + ] + }, + "step": { + "description": "Information about the step.", + "allOf": [ + { + "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" + } + ] + }, + "step_elapsed": { + "description": "Total time elapsed since the start of the step. Includes prior attempts.", + "allOf": [ + { + "$ref": "#/definitions/Duration" + } + ] + } + } + }, + { + "description": "Future variants that might be unknown.", + "type": "object", + "required": [ + "kind" + ], + "properties": { + "kind": { + "type": "string", + "enum": [ + "unknown" + ] + } + } + } + ] + }, + "ProgressUnits": { + "type": "string", + "x-rust-type": { + "crate": "oxide-update-engine-types", + "path": "oxide_update_engine_types::events::ProgressUnits", + "version": "0.1.0" + } + }, + "StepComponentSummaryForGenericSpec": { + "type": "object", + "required": [ + "component", + "total_component_steps" + ], + "properties": { + "component": { + "description": "The component." + }, + "total_component_steps": { + "description": "The number of steps present in this component.", + "type": "integer", + "format": "uint", + "minimum": 0.0 + } + } + }, + "StepEventForGenericSpec": { + "type": "object", + "required": [ + "data", + "event_index", + "execution_id", + "spec", + "total_elapsed" + ], + "properties": { + "data": { + "description": "The kind of event this is.", + "allOf": [ + { + "$ref": "#/definitions/StepEventKindForGenericSpec" + } + ] + }, + "event_index": { + "description": "A monotonically increasing index for this `StepEvent`.", + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "execution_id": { + "description": "The execution ID.", + "allOf": [ + { + "$ref": "#/definitions/ExecutionUuid" + } + ] + }, + "spec": { + "description": "The specification that this event belongs to.", + "type": "string" + }, + "total_elapsed": { + "description": "Total time elapsed since the start of execution.", + "allOf": [ + { + "$ref": "#/definitions/Duration" + } + ] + } + }, + "x-rust-type": { + "crate": "oxide-update-engine-types", + "parameters": [ + { + "x-rust-type": { + "crate": "oxide-update-engine-types", + "path": "oxide_update_engine_types::spec::GenericSpec", + "version": "0.1.0" + } + } + ], + "path": "oxide_update_engine_types::events::StepEvent", + "version": "0.1.0" + } + }, + "StepEventKindForGenericSpec": { + "oneOf": [ + { + "description": "No steps were defined, and the executor exited without doing anything.\n\nThis is a terminal event: it is guaranteed that no more events will be seen after this one.", + "type": "object", + "required": [ + "kind" + ], + "properties": { + "kind": { + "type": "string", + "enum": [ + "no_steps_defined" + ] + } + } + }, + { + "description": "Execution was started.\n\nThis is an initial event -- it is always expected to be the first event received from the event stream.", + "type": "object", + "required": [ + "components", + "first_step", + "kind", + "steps" + ], + "properties": { + "components": { + "description": "A list of components, along with the number of items each component has.", + "type": "array", + "items": { + "$ref": "#/definitions/StepComponentSummaryForGenericSpec" + } + }, + "first_step": { + "description": "Information about the first step.", + "allOf": [ + { + "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" + } + ] + }, + "kind": { + "type": "string", + "enum": [ + "execution_started" + ] + }, + "steps": { + "description": "The list of steps that will be executed.", + "type": "array", + "items": { + "$ref": "#/definitions/StepInfoForGenericSpec" + } + } + } + }, + { + "description": "Progress was reset along an attempt, and this attempt is going down a different path.", + "type": "object", + "required": [ + "attempt", + "attempt_elapsed", + "kind", + "message", + "metadata", + "step", + "step_elapsed" + ], + "properties": { + "attempt": { + "description": "The current attempt number.", + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "attempt_elapsed": { + "description": "The amount of time this attempt has taken so far.", + "allOf": [ + { + "$ref": "#/definitions/Duration" + } + ] + }, + "kind": { + "type": "string", + "enum": [ + "progress_reset" + ] + }, + "message": { + "description": "A message associated with the reset.", + "type": "string" + }, + "metadata": { + "description": "Progress-related metadata associated with this attempt." + }, + "step": { + "description": "Information about the step.", + "allOf": [ + { + "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" + } + ] + }, + "step_elapsed": { + "description": "Total time elapsed since the start of the step. Includes prior attempts.", + "allOf": [ + { + "$ref": "#/definitions/Duration" + } + ] + } + } + }, + { + "description": "An attempt failed and this step is being retried.", + "type": "object", + "required": [ + "attempt_elapsed", + "kind", + "message", + "next_attempt", + "step", + "step_elapsed" + ], + "properties": { + "attempt_elapsed": { + "description": "The amount of time the previous attempt took.", + "allOf": [ + { + "$ref": "#/definitions/Duration" + } + ] + }, + "kind": { + "type": "string", + "enum": [ + "attempt_retry" + ] + }, + "message": { + "description": "A message associated with the retry.", + "type": "string" + }, + "next_attempt": { + "description": "The attempt number for the next attempt.", + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "step": { + "description": "Information about the step.", + "allOf": [ + { + "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" + } + ] + }, + "step_elapsed": { + "description": "Total time elapsed since the start of the step. Includes prior attempts.", + "allOf": [ + { + "$ref": "#/definitions/Duration" + } + ] + } + } + }, + { + "description": "A step is complete and the next step has been started.", + "type": "object", + "required": [ + "attempt", + "attempt_elapsed", + "kind", + "next_step", + "outcome", + "step", + "step_elapsed" + ], + "properties": { + "attempt": { + "description": "The attempt number that completed.", + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "attempt_elapsed": { + "description": "The time it took for this attempt to complete.", + "allOf": [ + { + "$ref": "#/definitions/Duration" + } + ] + }, + "kind": { + "type": "string", + "enum": [ + "step_completed" + ] + }, + "next_step": { + "description": "The next step that is being started.", + "allOf": [ + { + "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" + } + ] + }, + "outcome": { + "description": "The outcome of the step.", + "allOf": [ + { + "$ref": "#/definitions/StepOutcomeForGenericSpec" + } + ] + }, + "step": { + "description": "Information about the step that just completed.", + "allOf": [ + { + "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" + } + ] + }, + "step_elapsed": { + "description": "Total time elapsed since the start of the step. Includes prior attempts.", + "allOf": [ + { + "$ref": "#/definitions/Duration" + } + ] + } + } + }, + { + "description": "Execution is complete.\n\nThis is a terminal event: it is guaranteed that no more events will be seen after this one.", + "type": "object", + "required": [ + "attempt_elapsed", + "kind", + "last_attempt", + "last_outcome", + "last_step", + "step_elapsed" + ], + "properties": { + "attempt_elapsed": { + "description": "The time it took for this attempt to complete.", + "allOf": [ + { + "$ref": "#/definitions/Duration" + } + ] + }, + "kind": { + "type": "string", + "enum": [ + "execution_completed" + ] + }, + "last_attempt": { + "description": "The attempt number that completed.", + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "last_outcome": { + "description": "The outcome of the last step.", + "allOf": [ + { + "$ref": "#/definitions/StepOutcomeForGenericSpec" + } + ] + }, + "last_step": { + "description": "Information about the last step that completed.", + "allOf": [ + { + "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" + } + ] + }, + "step_elapsed": { + "description": "Total time elapsed since the start of the step. Includes prior attempts.", + "allOf": [ + { + "$ref": "#/definitions/Duration" + } + ] + } + } + }, + { + "description": "Execution failed.\n\nThis is a terminal event: it is guaranteed that no more events will be seen after this one.", + "type": "object", + "required": [ + "attempt_elapsed", + "causes", + "failed_step", + "kind", + "message", + "step_elapsed", + "total_attempts" + ], + "properties": { + "attempt_elapsed": { + "description": "The time it took for this attempt to complete.", + "allOf": [ + { + "$ref": "#/definitions/Duration" + } + ] + }, + "causes": { + "description": "A chain of causes associated with the failure.", + "type": "array", + "items": { + "type": "string" + } + }, + "failed_step": { + "description": "Information about the step that failed.", + "allOf": [ + { + "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" + } + ] + }, + "kind": { + "type": "string", + "enum": [ + "execution_failed" + ] + }, + "message": { + "description": "A message associated with the failure.", + "type": "string" + }, + "step_elapsed": { + "description": "Total time elapsed since the start of the step. Includes prior attempts.", + "allOf": [ + { + "$ref": "#/definitions/Duration" + } + ] + }, + "total_attempts": { + "description": "The total number of attempts that were performed before the step failed.", + "type": "integer", + "format": "uint", + "minimum": 0.0 + } + } + }, + { + "description": "Execution aborted by an external user.\n\nThis is a terminal event: it is guaranteed that no more events will be seen after this one.", + "type": "object", + "required": [ + "aborted_step", + "attempt", + "attempt_elapsed", + "kind", + "message", + "step_elapsed" + ], + "properties": { + "aborted_step": { + "description": "Information about the step that was running at the time execution was aborted.", + "allOf": [ + { + "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" + } + ] + }, + "attempt": { + "description": "The attempt that was running at the time the step was aborted.", + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "attempt_elapsed": { + "description": "The time it took for this attempt to complete.", + "allOf": [ + { + "$ref": "#/definitions/Duration" + } + ] + }, + "kind": { + "type": "string", + "enum": [ + "execution_aborted" + ] + }, + "message": { + "description": "A message associated with the abort.", + "type": "string" + }, + "step_elapsed": { + "description": "Total time elapsed since the start of the step. Includes prior attempts.", + "allOf": [ + { + "$ref": "#/definitions/Duration" + } + ] + } + } + }, + { + "description": "A nested step event occurred.", + "type": "object", + "required": [ + "attempt", + "attempt_elapsed", + "event", + "kind", + "step", + "step_elapsed" + ], + "properties": { + "attempt": { + "description": "The current attempt number.", + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "attempt_elapsed": { + "description": "The time it took for this attempt to complete.", + "allOf": [ + { + "$ref": "#/definitions/Duration" + } + ] + }, + "event": { + "description": "The event that occurred.", + "allOf": [ + { + "$ref": "#/definitions/StepEventForGenericSpec" + } + ] + }, + "kind": { + "type": "string", + "enum": [ + "nested" + ] + }, + "step": { + "description": "Information about the step that's occurring.", + "allOf": [ + { + "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" + } + ] + }, + "step_elapsed": { + "description": "Total time elapsed since the start of the step. Includes prior attempts.", + "allOf": [ + { + "$ref": "#/definitions/Duration" + } + ] + } + } + }, + { + "description": "Future variants that might be unknown.", + "type": "object", + "required": [ + "kind" + ], + "properties": { + "kind": { + "type": "string", + "enum": [ + "unknown" + ] + } + } + } + ] + }, + "StepInfoForGenericSpec": { + "description": "Serializable information about a step.", + "type": "object", + "required": [ + "component", + "component_index", + "description", + "id", + "index", + "total_component_steps" + ], + "properties": { + "component": { + "description": "The component that this step is part of." + }, + "component_index": { + "description": "The index of the step within the component.", + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "description": { + "description": "The description for this step.", + "type": "string" + }, + "id": { + "description": "An identifier for this step." + }, + "index": { + "description": "The index of the step within all steps to be executed.", + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "total_component_steps": { + "description": "The total number of steps in this component.", + "type": "integer", + "format": "uint", + "minimum": 0.0 + } + } + }, + "StepInfoWithMetadataForGenericSpec": { + "description": "Serializable information about a step.", + "type": "object", + "required": [ + "info" + ], + "properties": { + "info": { + "description": "Information about this step.", + "allOf": [ + { + "$ref": "#/definitions/StepInfoForGenericSpec" + } + ] + }, + "metadata": { + "description": "Additional metadata associated with this step." + } + } + }, + "StepOutcomeForGenericSpec": { + "oneOf": [ + { + "description": "The step completed successfully.", + "type": "object", + "required": [ + "kind" + ], + "properties": { + "kind": { + "type": "string", + "enum": [ + "success" + ] + }, + "message": { + "description": "An optional message associated with this step.", + "type": [ + "string", + "null" + ] + }, + "metadata": { + "description": "Optional completion metadata associated with the step." + } + } + }, + { + "description": "The step completed with a warning.", + "type": "object", + "required": [ + "kind", + "message" + ], + "properties": { + "kind": { + "type": "string", + "enum": [ + "warning" + ] + }, + "message": { + "description": "A warning message.", + "type": "string" + }, + "metadata": { + "description": "Optional completion metadata associated with the step." + } + } + }, + { + "description": "The step was skipped with a message.", + "type": "object", + "required": [ + "kind", + "message" + ], + "properties": { + "kind": { + "type": "string", + "enum": [ + "skipped" + ] + }, + "message": { + "description": "Message associated with the skip.", + "type": "string" + }, + "metadata": { + "description": "Optional metadata associated with the skip." + } + } + } + ] + } + } +} \ No newline at end of file diff --git a/typify-example/Cargo.toml b/typify-example/Cargo.toml new file mode 100644 index 0000000..458a73f --- /dev/null +++ b/typify-example/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "typify-example" +version = "0.0.0" +edition.workspace = true +publish = false + +[dev-dependencies] +anyhow.workspace = true +expectorate.workspace = true +oxide-update-engine-types = { workspace = true, features = ["schemars08"] } +prettyplease.workspace = true +schemars.workspace = true +serde_json.workspace = true +syn.workspace = true +typify.workspace = true diff --git a/typify-example/README.md b/typify-example/README.md new file mode 100644 index 0000000..de00042 --- /dev/null +++ b/typify-example/README.md @@ -0,0 +1,4 @@ +# Example for typify automatic replacement + +This crate demos typify's automatic replacement with `x-rust-type`. + diff --git a/typify-example/src/lib.rs b/typify-example/src/lib.rs new file mode 100644 index 0000000..4ec90b9 --- /dev/null +++ b/typify-example/src/lib.rs @@ -0,0 +1,132 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +//! Verification that typify correctly resolves `x-rust-type` +//! annotations from `oxide-update-engine-types` schemas. +//! +//! The test defines a wrapper struct that *contains* an +//! `EventReport`. When typify processes the wrapper's +//! schema, it should replace `EventReport` (and its transitive +//! dependencies like `StepEvent`, `ProgressEvent`, `ProgressCounter`, +//! etc.) with references to the real types via `x-rust-type`, rather +//! than generating new struct definitions for them. + +#[cfg(test)] +mod tests { + use expectorate::assert_contents; + use oxide_update_engine_types::{ + events::EventReport, + schema::RustTypeInfo, + spec::{EngineSpec, GenericSpec}, + }; + + /// A wrapper struct that references `EventReport`. + /// + /// Typify will generate this struct, but should use the real + /// `EventReport` type (and its transitive dependencies) for + /// the `report` field via `x-rust-type` replacement. + #[derive(schemars::JsonSchema)] + #[expect(dead_code)] + struct Wrapper { + report: EventReport, + } + + #[test] + fn typify_resolves_event_report_schema() { + let schema = schemars::schema_for!(Wrapper); + + let mut settings = typify::TypeSpaceSettings::default(); + settings.with_crate( + "oxide-update-engine-types", + typify::CrateVers::Any, + None, + ); + + let mut type_space = typify::TypeSpace::new(&settings); + type_space.add_root_schema(schema).expect("added root schema"); + + let code = type_space.to_stream(); + let file = + syn::parse2::(code).expect("parsed generated code"); + let formatted = prettyplease::unparse(&file); + + assert_contents("tests/output/event_report_typify.rs", &formatted); + } + + // -- External (user-defined) spec -- + + /// A spec type simulating a user-defined spec in an external + /// crate. Its `rust_type_info()` points to `"typify-example"` + /// rather than `"oxide-update-engine-types"`. + enum ExternalSpec {} + + impl EngineSpec for ExternalSpec { + fn spec_name() -> String { + "ExternalSpec".to_owned() + } + + type Component = serde_json::Value; + type StepId = serde_json::Value; + type StepMetadata = serde_json::Value; + type ProgressMetadata = serde_json::Value; + type CompletionMetadata = serde_json::Value; + type SkippedMetadata = serde_json::Value; + type Error = anyhow::Error; + + fn rust_type_info() -> Option { + Some(RustTypeInfo { + crate_name: "typify-example", + version: "*", + path: "typify_example::ExternalSpec", + }) + } + } + + impl schemars::JsonSchema for ExternalSpec { + fn schema_name() -> String { + "ExternalSpec".to_owned() + } + + fn json_schema( + _: &mut schemars::r#gen::SchemaGenerator, + ) -> schemars::schema::Schema { + schemars::schema::Schema::Bool(true) + } + } + + /// A wrapper struct that references + /// `EventReport`. + /// + /// The outer types should resolve to + /// `::oxide_update_engine_types::...` while the parameter + /// should resolve to `::typify_example::ExternalSpec`. + #[derive(schemars::JsonSchema)] + #[expect(dead_code)] + struct ExternalWrapper { + report: EventReport, + } + + #[test] + fn typify_resolves_external_spec_schema() { + let schema = schemars::schema_for!(ExternalWrapper); + + let mut settings = typify::TypeSpaceSettings::default(); + settings.with_crate( + "oxide-update-engine-types", + typify::CrateVers::Any, + None, + ); + settings.with_crate("typify-example", typify::CrateVers::Any, None); + + let mut type_space = typify::TypeSpace::new(&settings); + type_space.add_root_schema(schema).expect("added root schema"); + + let code = type_space.to_stream(); + let file = + syn::parse2::(code).expect("parsed generated code"); + let formatted = prettyplease::unparse(&file); + + assert_contents("tests/output/external_spec_typify.rs", &formatted); + } +} diff --git a/typify-example/tests/output/event_report_typify.rs b/typify-example/tests/output/event_report_typify.rs new file mode 100644 index 0000000..98a7e4f --- /dev/null +++ b/typify-example/tests/output/event_report_typify.rs @@ -0,0 +1,1208 @@ +/// Error types. +pub mod error { + /// Error from a `TryFrom` or `FromStr` implementation. + pub struct ConversionError(::std::borrow::Cow<'static, str>); + impl ::std::error::Error for ConversionError {} + impl ::std::fmt::Display for ConversionError { + fn fmt( + &self, + f: &mut ::std::fmt::Formatter<'_>, + ) -> Result<(), ::std::fmt::Error> { + ::std::fmt::Display::fmt(&self.0, f) + } + } + impl ::std::fmt::Debug for ConversionError { + fn fmt( + &self, + f: &mut ::std::fmt::Formatter<'_>, + ) -> Result<(), ::std::fmt::Error> { + ::std::fmt::Debug::fmt(&self.0, f) + } + } + impl From<&'static str> for ConversionError { + fn from(value: &'static str) -> Self { + Self(value.into()) + } + } + impl From for ConversionError { + fn from(value: String) -> Self { + Self(value.into()) + } + } +} +///`Duration` +/// +///
JSON schema +/// +/// ```json +///{ +/// "type": "object", +/// "required": [ +/// "nanos", +/// "secs" +/// ], +/// "properties": { +/// "nanos": { +/// "type": "integer", +/// "format": "uint32", +/// "minimum": 0.0 +/// }, +/// "secs": { +/// "type": "integer", +/// "format": "uint64", +/// "minimum": 0.0 +/// } +/// } +///} +/// ``` +///
+#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)] +pub struct Duration { + pub nanos: u32, + pub secs: u64, +} +///`ProgressEventKindForGenericSpec` +/// +///
JSON schema +/// +/// ```json +///{ +/// "oneOf": [ +/// { +/// "description": "The update engine is waiting for a progress message.\n\nThe update engine sends this message immediately after a [`StepEvent`] corresponding to a new step.", +/// "type": "object", +/// "required": [ +/// "attempt", +/// "attempt_elapsed", +/// "kind", +/// "step", +/// "step_elapsed" +/// ], +/// "properties": { +/// "attempt": { +/// "description": "The attempt number currently being executed.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "attempt_elapsed": { +/// "description": "Total time elapsed since the start of the attempt.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "waiting_for_progress" +/// ] +/// }, +/// "step": { +/// "description": "Information about the step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" +/// } +/// ] +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "type": "object", +/// "required": [ +/// "attempt", +/// "attempt_elapsed", +/// "kind", +/// "metadata", +/// "step", +/// "step_elapsed" +/// ], +/// "properties": { +/// "attempt": { +/// "description": "The attempt number currently being executed.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "attempt_elapsed": { +/// "description": "Total time elapsed since the start of the attempt.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "progress" +/// ] +/// }, +/// "metadata": { +/// "description": "Metadata that was returned with progress." +/// }, +/// "progress": { +/// "description": "Current progress.", +/// "anyOf": [ +/// { +/// "$ref": "#/definitions/ProgressCounter" +/// }, +/// { +/// "type": "null" +/// } +/// ] +/// }, +/// "step": { +/// "description": "Information about the step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" +/// } +/// ] +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "type": "object", +/// "required": [ +/// "attempt", +/// "attempt_elapsed", +/// "event", +/// "kind", +/// "step", +/// "step_elapsed" +/// ], +/// "properties": { +/// "attempt": { +/// "description": "The attempt number currently being executed.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "attempt_elapsed": { +/// "description": "The time it took for this attempt to complete.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "event": { +/// "description": "The event that occurred.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/ProgressEventForGenericSpec" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "nested" +/// ] +/// }, +/// "step": { +/// "description": "Information about the step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" +/// } +/// ] +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "description": "Future variants that might be unknown.", +/// "type": "object", +/// "required": [ +/// "kind" +/// ], +/// "properties": { +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "unknown" +/// ] +/// } +/// } +/// } +/// ] +///} +/// ``` +///
+#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)] +#[serde(tag = "kind")] +pub enum ProgressEventKindForGenericSpec { + /**The update engine is waiting for a progress message. + +The update engine sends this message immediately after a [`StepEvent`] corresponding to a new step.*/ + #[serde(rename = "waiting_for_progress")] + WaitingForProgress { + ///The attempt number currently being executed. + attempt: u32, + ///Total time elapsed since the start of the attempt. + attempt_elapsed: Duration, + ///Information about the step. + step: StepInfoWithMetadataForGenericSpec, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + #[serde(rename = "progress")] + Progress { + ///The attempt number currently being executed. + attempt: u32, + ///Total time elapsed since the start of the attempt. + attempt_elapsed: Duration, + ///Metadata that was returned with progress. + metadata: ::serde_json::Value, + ///Current progress. + #[serde(default, skip_serializing_if = "::std::option::Option::is_none")] + progress: ::std::option::Option< + ::oxide_update_engine_types::events::ProgressCounter, + >, + ///Information about the step. + step: StepInfoWithMetadataForGenericSpec, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + #[serde(rename = "nested")] + Nested { + ///The attempt number currently being executed. + attempt: u32, + ///The time it took for this attempt to complete. + attempt_elapsed: Duration, + ///The event that occurred. + event: ::oxide_update_engine_types::events::ProgressEvent< + ::oxide_update_engine_types::spec::GenericSpec, + >, + ///Information about the step. + step: StepInfoWithMetadataForGenericSpec, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + #[serde(rename = "unknown")] + Unknown, +} +///`StepComponentSummaryForGenericSpec` +/// +///
JSON schema +/// +/// ```json +///{ +/// "type": "object", +/// "required": [ +/// "component", +/// "total_component_steps" +/// ], +/// "properties": { +/// "component": { +/// "description": "The component." +/// }, +/// "total_component_steps": { +/// "description": "The number of steps present in this component.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// } +/// } +///} +/// ``` +///
+#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)] +pub struct StepComponentSummaryForGenericSpec { + ///The component. + pub component: ::serde_json::Value, + ///The number of steps present in this component. + pub total_component_steps: u32, +} +///`StepEventKindForGenericSpec` +/// +///
JSON schema +/// +/// ```json +///{ +/// "oneOf": [ +/// { +/// "description": "No steps were defined, and the executor exited without doing anything.\n\nThis is a terminal event: it is guaranteed that no more events will be seen after this one.", +/// "type": "object", +/// "required": [ +/// "kind" +/// ], +/// "properties": { +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "no_steps_defined" +/// ] +/// } +/// } +/// }, +/// { +/// "description": "Execution was started.\n\nThis is an initial event -- it is always expected to be the first event received from the event stream.", +/// "type": "object", +/// "required": [ +/// "components", +/// "first_step", +/// "kind", +/// "steps" +/// ], +/// "properties": { +/// "components": { +/// "description": "A list of components, along with the number of items each component has.", +/// "type": "array", +/// "items": { +/// "$ref": "#/definitions/StepComponentSummaryForGenericSpec" +/// } +/// }, +/// "first_step": { +/// "description": "Information about the first step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "execution_started" +/// ] +/// }, +/// "steps": { +/// "description": "The list of steps that will be executed.", +/// "type": "array", +/// "items": { +/// "$ref": "#/definitions/StepInfoForGenericSpec" +/// } +/// } +/// } +/// }, +/// { +/// "description": "Progress was reset along an attempt, and this attempt is going down a different path.", +/// "type": "object", +/// "required": [ +/// "attempt", +/// "attempt_elapsed", +/// "kind", +/// "message", +/// "metadata", +/// "step", +/// "step_elapsed" +/// ], +/// "properties": { +/// "attempt": { +/// "description": "The current attempt number.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "attempt_elapsed": { +/// "description": "The amount of time this attempt has taken so far.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "progress_reset" +/// ] +/// }, +/// "message": { +/// "description": "A message associated with the reset.", +/// "type": "string" +/// }, +/// "metadata": { +/// "description": "Progress-related metadata associated with this attempt." +/// }, +/// "step": { +/// "description": "Information about the step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" +/// } +/// ] +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "description": "An attempt failed and this step is being retried.", +/// "type": "object", +/// "required": [ +/// "attempt_elapsed", +/// "kind", +/// "message", +/// "next_attempt", +/// "step", +/// "step_elapsed" +/// ], +/// "properties": { +/// "attempt_elapsed": { +/// "description": "The amount of time the previous attempt took.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "attempt_retry" +/// ] +/// }, +/// "message": { +/// "description": "A message associated with the retry.", +/// "type": "string" +/// }, +/// "next_attempt": { +/// "description": "The attempt number for the next attempt.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "step": { +/// "description": "Information about the step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" +/// } +/// ] +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "description": "A step is complete and the next step has been started.", +/// "type": "object", +/// "required": [ +/// "attempt", +/// "attempt_elapsed", +/// "kind", +/// "next_step", +/// "outcome", +/// "step", +/// "step_elapsed" +/// ], +/// "properties": { +/// "attempt": { +/// "description": "The attempt number that completed.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "attempt_elapsed": { +/// "description": "The time it took for this attempt to complete.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "step_completed" +/// ] +/// }, +/// "next_step": { +/// "description": "The next step that is being started.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" +/// } +/// ] +/// }, +/// "outcome": { +/// "description": "The outcome of the step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepOutcomeForGenericSpec" +/// } +/// ] +/// }, +/// "step": { +/// "description": "Information about the step that just completed.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" +/// } +/// ] +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "description": "Execution is complete.\n\nThis is a terminal event: it is guaranteed that no more events will be seen after this one.", +/// "type": "object", +/// "required": [ +/// "attempt_elapsed", +/// "kind", +/// "last_attempt", +/// "last_outcome", +/// "last_step", +/// "step_elapsed" +/// ], +/// "properties": { +/// "attempt_elapsed": { +/// "description": "The time it took for this attempt to complete.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "execution_completed" +/// ] +/// }, +/// "last_attempt": { +/// "description": "The attempt number that completed.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "last_outcome": { +/// "description": "The outcome of the last step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepOutcomeForGenericSpec" +/// } +/// ] +/// }, +/// "last_step": { +/// "description": "Information about the last step that completed.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" +/// } +/// ] +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "description": "Execution failed.\n\nThis is a terminal event: it is guaranteed that no more events will be seen after this one.", +/// "type": "object", +/// "required": [ +/// "attempt_elapsed", +/// "causes", +/// "failed_step", +/// "kind", +/// "message", +/// "step_elapsed", +/// "total_attempts" +/// ], +/// "properties": { +/// "attempt_elapsed": { +/// "description": "The time it took for this attempt to complete.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "causes": { +/// "description": "A chain of causes associated with the failure.", +/// "type": "array", +/// "items": { +/// "type": "string" +/// } +/// }, +/// "failed_step": { +/// "description": "Information about the step that failed.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "execution_failed" +/// ] +/// }, +/// "message": { +/// "description": "A message associated with the failure.", +/// "type": "string" +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "total_attempts": { +/// "description": "The total number of attempts that were performed before the step failed.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// } +/// } +/// }, +/// { +/// "description": "Execution aborted by an external user.\n\nThis is a terminal event: it is guaranteed that no more events will be seen after this one.", +/// "type": "object", +/// "required": [ +/// "aborted_step", +/// "attempt", +/// "attempt_elapsed", +/// "kind", +/// "message", +/// "step_elapsed" +/// ], +/// "properties": { +/// "aborted_step": { +/// "description": "Information about the step that was running at the time execution was aborted.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" +/// } +/// ] +/// }, +/// "attempt": { +/// "description": "The attempt that was running at the time the step was aborted.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "attempt_elapsed": { +/// "description": "The time it took for this attempt to complete.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "execution_aborted" +/// ] +/// }, +/// "message": { +/// "description": "A message associated with the abort.", +/// "type": "string" +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "description": "A nested step event occurred.", +/// "type": "object", +/// "required": [ +/// "attempt", +/// "attempt_elapsed", +/// "event", +/// "kind", +/// "step", +/// "step_elapsed" +/// ], +/// "properties": { +/// "attempt": { +/// "description": "The current attempt number.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "attempt_elapsed": { +/// "description": "The time it took for this attempt to complete.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "event": { +/// "description": "The event that occurred.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepEventForGenericSpec" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "nested" +/// ] +/// }, +/// "step": { +/// "description": "Information about the step that's occurring.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" +/// } +/// ] +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "description": "Future variants that might be unknown.", +/// "type": "object", +/// "required": [ +/// "kind" +/// ], +/// "properties": { +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "unknown" +/// ] +/// } +/// } +/// } +/// ] +///} +/// ``` +///
+#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)] +#[serde(tag = "kind")] +pub enum StepEventKindForGenericSpec { + #[serde(rename = "no_steps_defined")] + NoStepsDefined, + /**Execution was started. + +This is an initial event -- it is always expected to be the first event received from the event stream.*/ + #[serde(rename = "execution_started")] + ExecutionStarted { + ///A list of components, along with the number of items each component has. + components: ::std::vec::Vec, + ///Information about the first step. + first_step: StepInfoWithMetadataForGenericSpec, + ///The list of steps that will be executed. + steps: ::std::vec::Vec, + }, + ///Progress was reset along an attempt, and this attempt is going down a different path. + #[serde(rename = "progress_reset")] + ProgressReset { + ///The current attempt number. + attempt: u32, + ///The amount of time this attempt has taken so far. + attempt_elapsed: Duration, + ///A message associated with the reset. + message: ::std::string::String, + ///Progress-related metadata associated with this attempt. + metadata: ::serde_json::Value, + ///Information about the step. + step: StepInfoWithMetadataForGenericSpec, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + ///An attempt failed and this step is being retried. + #[serde(rename = "attempt_retry")] + AttemptRetry { + ///The amount of time the previous attempt took. + attempt_elapsed: Duration, + ///A message associated with the retry. + message: ::std::string::String, + ///The attempt number for the next attempt. + next_attempt: u32, + ///Information about the step. + step: StepInfoWithMetadataForGenericSpec, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + ///A step is complete and the next step has been started. + #[serde(rename = "step_completed")] + StepCompleted { + ///The attempt number that completed. + attempt: u32, + ///The time it took for this attempt to complete. + attempt_elapsed: Duration, + ///The next step that is being started. + next_step: StepInfoWithMetadataForGenericSpec, + ///The outcome of the step. + outcome: StepOutcomeForGenericSpec, + ///Information about the step that just completed. + step: StepInfoWithMetadataForGenericSpec, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + /**Execution is complete. + +This is a terminal event: it is guaranteed that no more events will be seen after this one.*/ + #[serde(rename = "execution_completed")] + ExecutionCompleted { + ///The time it took for this attempt to complete. + attempt_elapsed: Duration, + ///The attempt number that completed. + last_attempt: u32, + ///The outcome of the last step. + last_outcome: StepOutcomeForGenericSpec, + ///Information about the last step that completed. + last_step: StepInfoWithMetadataForGenericSpec, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + /**Execution failed. + +This is a terminal event: it is guaranteed that no more events will be seen after this one.*/ + #[serde(rename = "execution_failed")] + ExecutionFailed { + ///The time it took for this attempt to complete. + attempt_elapsed: Duration, + ///A chain of causes associated with the failure. + causes: ::std::vec::Vec<::std::string::String>, + ///Information about the step that failed. + failed_step: StepInfoWithMetadataForGenericSpec, + ///A message associated with the failure. + message: ::std::string::String, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + ///The total number of attempts that were performed before the step failed. + total_attempts: u32, + }, + /**Execution aborted by an external user. + +This is a terminal event: it is guaranteed that no more events will be seen after this one.*/ + #[serde(rename = "execution_aborted")] + ExecutionAborted { + ///Information about the step that was running at the time execution was aborted. + aborted_step: StepInfoWithMetadataForGenericSpec, + ///The attempt that was running at the time the step was aborted. + attempt: u32, + ///The time it took for this attempt to complete. + attempt_elapsed: Duration, + ///A message associated with the abort. + message: ::std::string::String, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + ///A nested step event occurred. + #[serde(rename = "nested")] + Nested { + ///The current attempt number. + attempt: u32, + ///The time it took for this attempt to complete. + attempt_elapsed: Duration, + ///The event that occurred. + event: ::oxide_update_engine_types::events::StepEvent< + ::oxide_update_engine_types::spec::GenericSpec, + >, + ///Information about the step that's occurring. + step: StepInfoWithMetadataForGenericSpec, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + #[serde(rename = "unknown")] + Unknown, +} +///Serializable information about a step. +/// +///
JSON schema +/// +/// ```json +///{ +/// "description": "Serializable information about a step.", +/// "type": "object", +/// "required": [ +/// "component", +/// "component_index", +/// "description", +/// "id", +/// "index", +/// "total_component_steps" +/// ], +/// "properties": { +/// "component": { +/// "description": "The component that this step is part of." +/// }, +/// "component_index": { +/// "description": "The index of the step within the component.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "description": { +/// "description": "The description for this step.", +/// "type": "string" +/// }, +/// "id": { +/// "description": "An identifier for this step." +/// }, +/// "index": { +/// "description": "The index of the step within all steps to be executed.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "total_component_steps": { +/// "description": "The total number of steps in this component.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// } +/// } +///} +/// ``` +///
+#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)] +pub struct StepInfoForGenericSpec { + ///The component that this step is part of. + pub component: ::serde_json::Value, + ///The index of the step within the component. + pub component_index: u32, + ///The description for this step. + pub description: ::std::string::String, + ///An identifier for this step. + pub id: ::serde_json::Value, + ///The index of the step within all steps to be executed. + pub index: u32, + ///The total number of steps in this component. + pub total_component_steps: u32, +} +///Serializable information about a step. +/// +///
JSON schema +/// +/// ```json +///{ +/// "description": "Serializable information about a step.", +/// "type": "object", +/// "required": [ +/// "info" +/// ], +/// "properties": { +/// "info": { +/// "description": "Information about this step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoForGenericSpec" +/// } +/// ] +/// }, +/// "metadata": { +/// "description": "Additional metadata associated with this step." +/// } +/// } +///} +/// ``` +///
+#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)] +pub struct StepInfoWithMetadataForGenericSpec { + ///Information about this step. + pub info: StepInfoForGenericSpec, + ///Additional metadata associated with this step. + #[serde(default, skip_serializing_if = "::std::option::Option::is_none")] + pub metadata: ::std::option::Option<::serde_json::Value>, +} +///`StepOutcomeForGenericSpec` +/// +///
JSON schema +/// +/// ```json +///{ +/// "oneOf": [ +/// { +/// "description": "The step completed successfully.", +/// "type": "object", +/// "required": [ +/// "kind" +/// ], +/// "properties": { +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "success" +/// ] +/// }, +/// "message": { +/// "description": "An optional message associated with this step.", +/// "type": [ +/// "string", +/// "null" +/// ] +/// }, +/// "metadata": { +/// "description": "Optional completion metadata associated with the step." +/// } +/// } +/// }, +/// { +/// "description": "The step completed with a warning.", +/// "type": "object", +/// "required": [ +/// "kind", +/// "message" +/// ], +/// "properties": { +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "warning" +/// ] +/// }, +/// "message": { +/// "description": "A warning message.", +/// "type": "string" +/// }, +/// "metadata": { +/// "description": "Optional completion metadata associated with the step." +/// } +/// } +/// }, +/// { +/// "description": "The step was skipped with a message.", +/// "type": "object", +/// "required": [ +/// "kind", +/// "message" +/// ], +/// "properties": { +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "skipped" +/// ] +/// }, +/// "message": { +/// "description": "Message associated with the skip.", +/// "type": "string" +/// }, +/// "metadata": { +/// "description": "Optional metadata associated with the skip." +/// } +/// } +/// } +/// ] +///} +/// ``` +///
+#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)] +#[serde(tag = "kind")] +pub enum StepOutcomeForGenericSpec { + ///The step completed successfully. + #[serde(rename = "success")] + Success { + ///An optional message associated with this step. + #[serde(default, skip_serializing_if = "::std::option::Option::is_none")] + message: ::std::option::Option<::std::string::String>, + ///Optional completion metadata associated with the step. + #[serde(default, skip_serializing_if = "::std::option::Option::is_none")] + metadata: ::std::option::Option<::serde_json::Value>, + }, + ///The step completed with a warning. + #[serde(rename = "warning")] + Warning { + ///A warning message. + message: ::std::string::String, + ///Optional completion metadata associated with the step. + #[serde(default, skip_serializing_if = "::std::option::Option::is_none")] + metadata: ::std::option::Option<::serde_json::Value>, + }, + ///The step was skipped with a message. + #[serde(rename = "skipped")] + Skipped { + ///Message associated with the skip. + message: ::std::string::String, + ///Optional metadata associated with the skip. + #[serde(default, skip_serializing_if = "::std::option::Option::is_none")] + metadata: ::std::option::Option<::serde_json::Value>, + }, +} +/**A wrapper struct that references `EventReport`. + +Typify will generate this struct, but should use the real `EventReport` type (and its transitive dependencies) for the `report` field via `x-rust-type` replacement.*/ +/// +///
JSON schema +/// +/// ```json +///{ +/// "title": "Wrapper", +/// "description": "A wrapper struct that references `EventReport`.\n\nTypify will generate this struct, but should use the real `EventReport` type (and its transitive dependencies) for the `report` field via `x-rust-type` replacement.", +/// "type": "object", +/// "required": [ +/// "report" +/// ], +/// "properties": { +/// "report": { +/// "$ref": "#/definitions/EventReportForGenericSpec" +/// } +/// } +///} +/// ``` +///
+#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)] +pub struct Wrapper { + pub report: ::oxide_update_engine_types::events::EventReport< + ::oxide_update_engine_types::spec::GenericSpec, + >, +} diff --git a/typify-example/tests/output/external_spec_typify.rs b/typify-example/tests/output/external_spec_typify.rs new file mode 100644 index 0000000..c008da9 --- /dev/null +++ b/typify-example/tests/output/external_spec_typify.rs @@ -0,0 +1,2325 @@ +/// Error types. +pub mod error { + /// Error from a `TryFrom` or `FromStr` implementation. + pub struct ConversionError(::std::borrow::Cow<'static, str>); + impl ::std::error::Error for ConversionError {} + impl ::std::fmt::Display for ConversionError { + fn fmt( + &self, + f: &mut ::std::fmt::Formatter<'_>, + ) -> Result<(), ::std::fmt::Error> { + ::std::fmt::Display::fmt(&self.0, f) + } + } + impl ::std::fmt::Debug for ConversionError { + fn fmt( + &self, + f: &mut ::std::fmt::Formatter<'_>, + ) -> Result<(), ::std::fmt::Error> { + ::std::fmt::Debug::fmt(&self.0, f) + } + } + impl From<&'static str> for ConversionError { + fn from(value: &'static str) -> Self { + Self(value.into()) + } + } + impl From for ConversionError { + fn from(value: String) -> Self { + Self(value.into()) + } + } +} +///`Duration` +/// +///
JSON schema +/// +/// ```json +///{ +/// "type": "object", +/// "required": [ +/// "nanos", +/// "secs" +/// ], +/// "properties": { +/// "nanos": { +/// "type": "integer", +/// "format": "uint32", +/// "minimum": 0.0 +/// }, +/// "secs": { +/// "type": "integer", +/// "format": "uint64", +/// "minimum": 0.0 +/// } +/// } +///} +/// ``` +///
+#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)] +pub struct Duration { + pub nanos: u32, + pub secs: u64, +} +/**A wrapper struct that references `EventReport`. + +The outer types should resolve to `::oxide_update_engine_types::...` while the parameter should resolve to `::typify_example::ExternalSpec`.*/ +/// +///
JSON schema +/// +/// ```json +///{ +/// "title": "ExternalWrapper", +/// "description": "A wrapper struct that references `EventReport`.\n\nThe outer types should resolve to `::oxide_update_engine_types::...` while the parameter should resolve to `::typify_example::ExternalSpec`.", +/// "type": "object", +/// "required": [ +/// "report" +/// ], +/// "properties": { +/// "report": { +/// "$ref": "#/definitions/EventReportForExternalSpec" +/// } +/// } +///} +/// ``` +///
+#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)] +pub struct ExternalWrapper { + pub report: ::oxide_update_engine_types::events::EventReport< + ::typify_example::ExternalSpec, + >, +} +///`ProgressEventKindForExternalSpec` +/// +///
JSON schema +/// +/// ```json +///{ +/// "oneOf": [ +/// { +/// "description": "The update engine is waiting for a progress message.\n\nThe update engine sends this message immediately after a [`StepEvent`] corresponding to a new step.", +/// "type": "object", +/// "required": [ +/// "attempt", +/// "attempt_elapsed", +/// "kind", +/// "step", +/// "step_elapsed" +/// ], +/// "properties": { +/// "attempt": { +/// "description": "The attempt number currently being executed.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "attempt_elapsed": { +/// "description": "Total time elapsed since the start of the attempt.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "waiting_for_progress" +/// ] +/// }, +/// "step": { +/// "description": "Information about the step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForExternalSpec" +/// } +/// ] +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "type": "object", +/// "required": [ +/// "attempt", +/// "attempt_elapsed", +/// "kind", +/// "metadata", +/// "step", +/// "step_elapsed" +/// ], +/// "properties": { +/// "attempt": { +/// "description": "The attempt number currently being executed.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "attempt_elapsed": { +/// "description": "Total time elapsed since the start of the attempt.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "progress" +/// ] +/// }, +/// "metadata": { +/// "description": "Metadata that was returned with progress." +/// }, +/// "progress": { +/// "description": "Current progress.", +/// "anyOf": [ +/// { +/// "$ref": "#/definitions/ProgressCounter" +/// }, +/// { +/// "type": "null" +/// } +/// ] +/// }, +/// "step": { +/// "description": "Information about the step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForExternalSpec" +/// } +/// ] +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "type": "object", +/// "required": [ +/// "attempt", +/// "attempt_elapsed", +/// "event", +/// "kind", +/// "step", +/// "step_elapsed" +/// ], +/// "properties": { +/// "attempt": { +/// "description": "The attempt number currently being executed.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "attempt_elapsed": { +/// "description": "The time it took for this attempt to complete.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "event": { +/// "description": "The event that occurred.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/ProgressEventForGenericSpec" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "nested" +/// ] +/// }, +/// "step": { +/// "description": "Information about the step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForExternalSpec" +/// } +/// ] +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "description": "Future variants that might be unknown.", +/// "type": "object", +/// "required": [ +/// "kind" +/// ], +/// "properties": { +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "unknown" +/// ] +/// } +/// } +/// } +/// ] +///} +/// ``` +///
+#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)] +#[serde(tag = "kind")] +pub enum ProgressEventKindForExternalSpec { + /**The update engine is waiting for a progress message. + +The update engine sends this message immediately after a [`StepEvent`] corresponding to a new step.*/ + #[serde(rename = "waiting_for_progress")] + WaitingForProgress { + ///The attempt number currently being executed. + attempt: u32, + ///Total time elapsed since the start of the attempt. + attempt_elapsed: Duration, + ///Information about the step. + step: StepInfoWithMetadataForExternalSpec, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + #[serde(rename = "progress")] + Progress { + ///The attempt number currently being executed. + attempt: u32, + ///Total time elapsed since the start of the attempt. + attempt_elapsed: Duration, + ///Metadata that was returned with progress. + metadata: ::serde_json::Value, + ///Current progress. + #[serde(default, skip_serializing_if = "::std::option::Option::is_none")] + progress: ::std::option::Option< + ::oxide_update_engine_types::events::ProgressCounter, + >, + ///Information about the step. + step: StepInfoWithMetadataForExternalSpec, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + #[serde(rename = "nested")] + Nested { + ///The attempt number currently being executed. + attempt: u32, + ///The time it took for this attempt to complete. + attempt_elapsed: Duration, + ///The event that occurred. + event: ::oxide_update_engine_types::events::ProgressEvent< + ::oxide_update_engine_types::spec::GenericSpec, + >, + ///Information about the step. + step: StepInfoWithMetadataForExternalSpec, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + #[serde(rename = "unknown")] + Unknown, +} +///`ProgressEventKindForGenericSpec` +/// +///
JSON schema +/// +/// ```json +///{ +/// "oneOf": [ +/// { +/// "description": "The update engine is waiting for a progress message.\n\nThe update engine sends this message immediately after a [`StepEvent`] corresponding to a new step.", +/// "type": "object", +/// "required": [ +/// "attempt", +/// "attempt_elapsed", +/// "kind", +/// "step", +/// "step_elapsed" +/// ], +/// "properties": { +/// "attempt": { +/// "description": "The attempt number currently being executed.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "attempt_elapsed": { +/// "description": "Total time elapsed since the start of the attempt.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "waiting_for_progress" +/// ] +/// }, +/// "step": { +/// "description": "Information about the step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" +/// } +/// ] +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "type": "object", +/// "required": [ +/// "attempt", +/// "attempt_elapsed", +/// "kind", +/// "metadata", +/// "step", +/// "step_elapsed" +/// ], +/// "properties": { +/// "attempt": { +/// "description": "The attempt number currently being executed.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "attempt_elapsed": { +/// "description": "Total time elapsed since the start of the attempt.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "progress" +/// ] +/// }, +/// "metadata": { +/// "description": "Metadata that was returned with progress." +/// }, +/// "progress": { +/// "description": "Current progress.", +/// "anyOf": [ +/// { +/// "$ref": "#/definitions/ProgressCounter" +/// }, +/// { +/// "type": "null" +/// } +/// ] +/// }, +/// "step": { +/// "description": "Information about the step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" +/// } +/// ] +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "type": "object", +/// "required": [ +/// "attempt", +/// "attempt_elapsed", +/// "event", +/// "kind", +/// "step", +/// "step_elapsed" +/// ], +/// "properties": { +/// "attempt": { +/// "description": "The attempt number currently being executed.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "attempt_elapsed": { +/// "description": "The time it took for this attempt to complete.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "event": { +/// "description": "The event that occurred.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/ProgressEventForGenericSpec" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "nested" +/// ] +/// }, +/// "step": { +/// "description": "Information about the step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" +/// } +/// ] +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "description": "Future variants that might be unknown.", +/// "type": "object", +/// "required": [ +/// "kind" +/// ], +/// "properties": { +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "unknown" +/// ] +/// } +/// } +/// } +/// ] +///} +/// ``` +///
+#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)] +#[serde(tag = "kind")] +pub enum ProgressEventKindForGenericSpec { + /**The update engine is waiting for a progress message. + +The update engine sends this message immediately after a [`StepEvent`] corresponding to a new step.*/ + #[serde(rename = "waiting_for_progress")] + WaitingForProgress { + ///The attempt number currently being executed. + attempt: u32, + ///Total time elapsed since the start of the attempt. + attempt_elapsed: Duration, + ///Information about the step. + step: StepInfoWithMetadataForGenericSpec, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + #[serde(rename = "progress")] + Progress { + ///The attempt number currently being executed. + attempt: u32, + ///Total time elapsed since the start of the attempt. + attempt_elapsed: Duration, + ///Metadata that was returned with progress. + metadata: ::serde_json::Value, + ///Current progress. + #[serde(default, skip_serializing_if = "::std::option::Option::is_none")] + progress: ::std::option::Option< + ::oxide_update_engine_types::events::ProgressCounter, + >, + ///Information about the step. + step: StepInfoWithMetadataForGenericSpec, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + #[serde(rename = "nested")] + Nested { + ///The attempt number currently being executed. + attempt: u32, + ///The time it took for this attempt to complete. + attempt_elapsed: Duration, + ///The event that occurred. + event: ::oxide_update_engine_types::events::ProgressEvent< + ::oxide_update_engine_types::spec::GenericSpec, + >, + ///Information about the step. + step: StepInfoWithMetadataForGenericSpec, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + #[serde(rename = "unknown")] + Unknown, +} +///`StepComponentSummaryForExternalSpec` +/// +///
JSON schema +/// +/// ```json +///{ +/// "type": "object", +/// "required": [ +/// "component", +/// "total_component_steps" +/// ], +/// "properties": { +/// "component": { +/// "description": "The component." +/// }, +/// "total_component_steps": { +/// "description": "The number of steps present in this component.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// } +/// } +///} +/// ``` +///
+#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)] +pub struct StepComponentSummaryForExternalSpec { + ///The component. + pub component: ::serde_json::Value, + ///The number of steps present in this component. + pub total_component_steps: u32, +} +///`StepComponentSummaryForGenericSpec` +/// +///
JSON schema +/// +/// ```json +///{ +/// "type": "object", +/// "required": [ +/// "component", +/// "total_component_steps" +/// ], +/// "properties": { +/// "component": { +/// "description": "The component." +/// }, +/// "total_component_steps": { +/// "description": "The number of steps present in this component.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// } +/// } +///} +/// ``` +///
+#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)] +pub struct StepComponentSummaryForGenericSpec { + ///The component. + pub component: ::serde_json::Value, + ///The number of steps present in this component. + pub total_component_steps: u32, +} +///`StepEventKindForExternalSpec` +/// +///
JSON schema +/// +/// ```json +///{ +/// "oneOf": [ +/// { +/// "description": "No steps were defined, and the executor exited without doing anything.\n\nThis is a terminal event: it is guaranteed that no more events will be seen after this one.", +/// "type": "object", +/// "required": [ +/// "kind" +/// ], +/// "properties": { +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "no_steps_defined" +/// ] +/// } +/// } +/// }, +/// { +/// "description": "Execution was started.\n\nThis is an initial event -- it is always expected to be the first event received from the event stream.", +/// "type": "object", +/// "required": [ +/// "components", +/// "first_step", +/// "kind", +/// "steps" +/// ], +/// "properties": { +/// "components": { +/// "description": "A list of components, along with the number of items each component has.", +/// "type": "array", +/// "items": { +/// "$ref": "#/definitions/StepComponentSummaryForExternalSpec" +/// } +/// }, +/// "first_step": { +/// "description": "Information about the first step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForExternalSpec" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "execution_started" +/// ] +/// }, +/// "steps": { +/// "description": "The list of steps that will be executed.", +/// "type": "array", +/// "items": { +/// "$ref": "#/definitions/StepInfoForExternalSpec" +/// } +/// } +/// } +/// }, +/// { +/// "description": "Progress was reset along an attempt, and this attempt is going down a different path.", +/// "type": "object", +/// "required": [ +/// "attempt", +/// "attempt_elapsed", +/// "kind", +/// "message", +/// "metadata", +/// "step", +/// "step_elapsed" +/// ], +/// "properties": { +/// "attempt": { +/// "description": "The current attempt number.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "attempt_elapsed": { +/// "description": "The amount of time this attempt has taken so far.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "progress_reset" +/// ] +/// }, +/// "message": { +/// "description": "A message associated with the reset.", +/// "type": "string" +/// }, +/// "metadata": { +/// "description": "Progress-related metadata associated with this attempt." +/// }, +/// "step": { +/// "description": "Information about the step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForExternalSpec" +/// } +/// ] +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "description": "An attempt failed and this step is being retried.", +/// "type": "object", +/// "required": [ +/// "attempt_elapsed", +/// "kind", +/// "message", +/// "next_attempt", +/// "step", +/// "step_elapsed" +/// ], +/// "properties": { +/// "attempt_elapsed": { +/// "description": "The amount of time the previous attempt took.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "attempt_retry" +/// ] +/// }, +/// "message": { +/// "description": "A message associated with the retry.", +/// "type": "string" +/// }, +/// "next_attempt": { +/// "description": "The attempt number for the next attempt.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "step": { +/// "description": "Information about the step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForExternalSpec" +/// } +/// ] +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "description": "A step is complete and the next step has been started.", +/// "type": "object", +/// "required": [ +/// "attempt", +/// "attempt_elapsed", +/// "kind", +/// "next_step", +/// "outcome", +/// "step", +/// "step_elapsed" +/// ], +/// "properties": { +/// "attempt": { +/// "description": "The attempt number that completed.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "attempt_elapsed": { +/// "description": "The time it took for this attempt to complete.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "step_completed" +/// ] +/// }, +/// "next_step": { +/// "description": "The next step that is being started.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForExternalSpec" +/// } +/// ] +/// }, +/// "outcome": { +/// "description": "The outcome of the step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepOutcomeForExternalSpec" +/// } +/// ] +/// }, +/// "step": { +/// "description": "Information about the step that just completed.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForExternalSpec" +/// } +/// ] +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "description": "Execution is complete.\n\nThis is a terminal event: it is guaranteed that no more events will be seen after this one.", +/// "type": "object", +/// "required": [ +/// "attempt_elapsed", +/// "kind", +/// "last_attempt", +/// "last_outcome", +/// "last_step", +/// "step_elapsed" +/// ], +/// "properties": { +/// "attempt_elapsed": { +/// "description": "The time it took for this attempt to complete.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "execution_completed" +/// ] +/// }, +/// "last_attempt": { +/// "description": "The attempt number that completed.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "last_outcome": { +/// "description": "The outcome of the last step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepOutcomeForExternalSpec" +/// } +/// ] +/// }, +/// "last_step": { +/// "description": "Information about the last step that completed.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForExternalSpec" +/// } +/// ] +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "description": "Execution failed.\n\nThis is a terminal event: it is guaranteed that no more events will be seen after this one.", +/// "type": "object", +/// "required": [ +/// "attempt_elapsed", +/// "causes", +/// "failed_step", +/// "kind", +/// "message", +/// "step_elapsed", +/// "total_attempts" +/// ], +/// "properties": { +/// "attempt_elapsed": { +/// "description": "The time it took for this attempt to complete.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "causes": { +/// "description": "A chain of causes associated with the failure.", +/// "type": "array", +/// "items": { +/// "type": "string" +/// } +/// }, +/// "failed_step": { +/// "description": "Information about the step that failed.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForExternalSpec" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "execution_failed" +/// ] +/// }, +/// "message": { +/// "description": "A message associated with the failure.", +/// "type": "string" +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "total_attempts": { +/// "description": "The total number of attempts that were performed before the step failed.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// } +/// } +/// }, +/// { +/// "description": "Execution aborted by an external user.\n\nThis is a terminal event: it is guaranteed that no more events will be seen after this one.", +/// "type": "object", +/// "required": [ +/// "aborted_step", +/// "attempt", +/// "attempt_elapsed", +/// "kind", +/// "message", +/// "step_elapsed" +/// ], +/// "properties": { +/// "aborted_step": { +/// "description": "Information about the step that was running at the time execution was aborted.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForExternalSpec" +/// } +/// ] +/// }, +/// "attempt": { +/// "description": "The attempt that was running at the time the step was aborted.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "attempt_elapsed": { +/// "description": "The time it took for this attempt to complete.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "execution_aborted" +/// ] +/// }, +/// "message": { +/// "description": "A message associated with the abort.", +/// "type": "string" +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "description": "A nested step event occurred.", +/// "type": "object", +/// "required": [ +/// "attempt", +/// "attempt_elapsed", +/// "event", +/// "kind", +/// "step", +/// "step_elapsed" +/// ], +/// "properties": { +/// "attempt": { +/// "description": "The current attempt number.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "attempt_elapsed": { +/// "description": "The time it took for this attempt to complete.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "event": { +/// "description": "The event that occurred.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepEventForGenericSpec" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "nested" +/// ] +/// }, +/// "step": { +/// "description": "Information about the step that's occurring.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForExternalSpec" +/// } +/// ] +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "description": "Future variants that might be unknown.", +/// "type": "object", +/// "required": [ +/// "kind" +/// ], +/// "properties": { +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "unknown" +/// ] +/// } +/// } +/// } +/// ] +///} +/// ``` +///
+#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)] +#[serde(tag = "kind")] +pub enum StepEventKindForExternalSpec { + #[serde(rename = "no_steps_defined")] + NoStepsDefined, + /**Execution was started. + +This is an initial event -- it is always expected to be the first event received from the event stream.*/ + #[serde(rename = "execution_started")] + ExecutionStarted { + ///A list of components, along with the number of items each component has. + components: ::std::vec::Vec, + ///Information about the first step. + first_step: StepInfoWithMetadataForExternalSpec, + ///The list of steps that will be executed. + steps: ::std::vec::Vec, + }, + ///Progress was reset along an attempt, and this attempt is going down a different path. + #[serde(rename = "progress_reset")] + ProgressReset { + ///The current attempt number. + attempt: u32, + ///The amount of time this attempt has taken so far. + attempt_elapsed: Duration, + ///A message associated with the reset. + message: ::std::string::String, + ///Progress-related metadata associated with this attempt. + metadata: ::serde_json::Value, + ///Information about the step. + step: StepInfoWithMetadataForExternalSpec, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + ///An attempt failed and this step is being retried. + #[serde(rename = "attempt_retry")] + AttemptRetry { + ///The amount of time the previous attempt took. + attempt_elapsed: Duration, + ///A message associated with the retry. + message: ::std::string::String, + ///The attempt number for the next attempt. + next_attempt: u32, + ///Information about the step. + step: StepInfoWithMetadataForExternalSpec, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + ///A step is complete and the next step has been started. + #[serde(rename = "step_completed")] + StepCompleted { + ///The attempt number that completed. + attempt: u32, + ///The time it took for this attempt to complete. + attempt_elapsed: Duration, + ///The next step that is being started. + next_step: StepInfoWithMetadataForExternalSpec, + ///The outcome of the step. + outcome: StepOutcomeForExternalSpec, + ///Information about the step that just completed. + step: StepInfoWithMetadataForExternalSpec, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + /**Execution is complete. + +This is a terminal event: it is guaranteed that no more events will be seen after this one.*/ + #[serde(rename = "execution_completed")] + ExecutionCompleted { + ///The time it took for this attempt to complete. + attempt_elapsed: Duration, + ///The attempt number that completed. + last_attempt: u32, + ///The outcome of the last step. + last_outcome: StepOutcomeForExternalSpec, + ///Information about the last step that completed. + last_step: StepInfoWithMetadataForExternalSpec, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + /**Execution failed. + +This is a terminal event: it is guaranteed that no more events will be seen after this one.*/ + #[serde(rename = "execution_failed")] + ExecutionFailed { + ///The time it took for this attempt to complete. + attempt_elapsed: Duration, + ///A chain of causes associated with the failure. + causes: ::std::vec::Vec<::std::string::String>, + ///Information about the step that failed. + failed_step: StepInfoWithMetadataForExternalSpec, + ///A message associated with the failure. + message: ::std::string::String, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + ///The total number of attempts that were performed before the step failed. + total_attempts: u32, + }, + /**Execution aborted by an external user. + +This is a terminal event: it is guaranteed that no more events will be seen after this one.*/ + #[serde(rename = "execution_aborted")] + ExecutionAborted { + ///Information about the step that was running at the time execution was aborted. + aborted_step: StepInfoWithMetadataForExternalSpec, + ///The attempt that was running at the time the step was aborted. + attempt: u32, + ///The time it took for this attempt to complete. + attempt_elapsed: Duration, + ///A message associated with the abort. + message: ::std::string::String, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + ///A nested step event occurred. + #[serde(rename = "nested")] + Nested { + ///The current attempt number. + attempt: u32, + ///The time it took for this attempt to complete. + attempt_elapsed: Duration, + ///The event that occurred. + event: ::oxide_update_engine_types::events::StepEvent< + ::oxide_update_engine_types::spec::GenericSpec, + >, + ///Information about the step that's occurring. + step: StepInfoWithMetadataForExternalSpec, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + #[serde(rename = "unknown")] + Unknown, +} +///`StepEventKindForGenericSpec` +/// +///
JSON schema +/// +/// ```json +///{ +/// "oneOf": [ +/// { +/// "description": "No steps were defined, and the executor exited without doing anything.\n\nThis is a terminal event: it is guaranteed that no more events will be seen after this one.", +/// "type": "object", +/// "required": [ +/// "kind" +/// ], +/// "properties": { +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "no_steps_defined" +/// ] +/// } +/// } +/// }, +/// { +/// "description": "Execution was started.\n\nThis is an initial event -- it is always expected to be the first event received from the event stream.", +/// "type": "object", +/// "required": [ +/// "components", +/// "first_step", +/// "kind", +/// "steps" +/// ], +/// "properties": { +/// "components": { +/// "description": "A list of components, along with the number of items each component has.", +/// "type": "array", +/// "items": { +/// "$ref": "#/definitions/StepComponentSummaryForGenericSpec" +/// } +/// }, +/// "first_step": { +/// "description": "Information about the first step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "execution_started" +/// ] +/// }, +/// "steps": { +/// "description": "The list of steps that will be executed.", +/// "type": "array", +/// "items": { +/// "$ref": "#/definitions/StepInfoForGenericSpec" +/// } +/// } +/// } +/// }, +/// { +/// "description": "Progress was reset along an attempt, and this attempt is going down a different path.", +/// "type": "object", +/// "required": [ +/// "attempt", +/// "attempt_elapsed", +/// "kind", +/// "message", +/// "metadata", +/// "step", +/// "step_elapsed" +/// ], +/// "properties": { +/// "attempt": { +/// "description": "The current attempt number.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "attempt_elapsed": { +/// "description": "The amount of time this attempt has taken so far.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "progress_reset" +/// ] +/// }, +/// "message": { +/// "description": "A message associated with the reset.", +/// "type": "string" +/// }, +/// "metadata": { +/// "description": "Progress-related metadata associated with this attempt." +/// }, +/// "step": { +/// "description": "Information about the step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" +/// } +/// ] +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "description": "An attempt failed and this step is being retried.", +/// "type": "object", +/// "required": [ +/// "attempt_elapsed", +/// "kind", +/// "message", +/// "next_attempt", +/// "step", +/// "step_elapsed" +/// ], +/// "properties": { +/// "attempt_elapsed": { +/// "description": "The amount of time the previous attempt took.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "attempt_retry" +/// ] +/// }, +/// "message": { +/// "description": "A message associated with the retry.", +/// "type": "string" +/// }, +/// "next_attempt": { +/// "description": "The attempt number for the next attempt.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "step": { +/// "description": "Information about the step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" +/// } +/// ] +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "description": "A step is complete and the next step has been started.", +/// "type": "object", +/// "required": [ +/// "attempt", +/// "attempt_elapsed", +/// "kind", +/// "next_step", +/// "outcome", +/// "step", +/// "step_elapsed" +/// ], +/// "properties": { +/// "attempt": { +/// "description": "The attempt number that completed.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "attempt_elapsed": { +/// "description": "The time it took for this attempt to complete.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "step_completed" +/// ] +/// }, +/// "next_step": { +/// "description": "The next step that is being started.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" +/// } +/// ] +/// }, +/// "outcome": { +/// "description": "The outcome of the step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepOutcomeForGenericSpec" +/// } +/// ] +/// }, +/// "step": { +/// "description": "Information about the step that just completed.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" +/// } +/// ] +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "description": "Execution is complete.\n\nThis is a terminal event: it is guaranteed that no more events will be seen after this one.", +/// "type": "object", +/// "required": [ +/// "attempt_elapsed", +/// "kind", +/// "last_attempt", +/// "last_outcome", +/// "last_step", +/// "step_elapsed" +/// ], +/// "properties": { +/// "attempt_elapsed": { +/// "description": "The time it took for this attempt to complete.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "execution_completed" +/// ] +/// }, +/// "last_attempt": { +/// "description": "The attempt number that completed.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "last_outcome": { +/// "description": "The outcome of the last step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepOutcomeForGenericSpec" +/// } +/// ] +/// }, +/// "last_step": { +/// "description": "Information about the last step that completed.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" +/// } +/// ] +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "description": "Execution failed.\n\nThis is a terminal event: it is guaranteed that no more events will be seen after this one.", +/// "type": "object", +/// "required": [ +/// "attempt_elapsed", +/// "causes", +/// "failed_step", +/// "kind", +/// "message", +/// "step_elapsed", +/// "total_attempts" +/// ], +/// "properties": { +/// "attempt_elapsed": { +/// "description": "The time it took for this attempt to complete.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "causes": { +/// "description": "A chain of causes associated with the failure.", +/// "type": "array", +/// "items": { +/// "type": "string" +/// } +/// }, +/// "failed_step": { +/// "description": "Information about the step that failed.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "execution_failed" +/// ] +/// }, +/// "message": { +/// "description": "A message associated with the failure.", +/// "type": "string" +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "total_attempts": { +/// "description": "The total number of attempts that were performed before the step failed.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// } +/// } +/// }, +/// { +/// "description": "Execution aborted by an external user.\n\nThis is a terminal event: it is guaranteed that no more events will be seen after this one.", +/// "type": "object", +/// "required": [ +/// "aborted_step", +/// "attempt", +/// "attempt_elapsed", +/// "kind", +/// "message", +/// "step_elapsed" +/// ], +/// "properties": { +/// "aborted_step": { +/// "description": "Information about the step that was running at the time execution was aborted.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" +/// } +/// ] +/// }, +/// "attempt": { +/// "description": "The attempt that was running at the time the step was aborted.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "attempt_elapsed": { +/// "description": "The time it took for this attempt to complete.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "execution_aborted" +/// ] +/// }, +/// "message": { +/// "description": "A message associated with the abort.", +/// "type": "string" +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "description": "A nested step event occurred.", +/// "type": "object", +/// "required": [ +/// "attempt", +/// "attempt_elapsed", +/// "event", +/// "kind", +/// "step", +/// "step_elapsed" +/// ], +/// "properties": { +/// "attempt": { +/// "description": "The current attempt number.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "attempt_elapsed": { +/// "description": "The time it took for this attempt to complete.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// }, +/// "event": { +/// "description": "The event that occurred.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepEventForGenericSpec" +/// } +/// ] +/// }, +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "nested" +/// ] +/// }, +/// "step": { +/// "description": "Information about the step that's occurring.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoWithMetadataForGenericSpec" +/// } +/// ] +/// }, +/// "step_elapsed": { +/// "description": "Total time elapsed since the start of the step. Includes prior attempts.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/Duration" +/// } +/// ] +/// } +/// } +/// }, +/// { +/// "description": "Future variants that might be unknown.", +/// "type": "object", +/// "required": [ +/// "kind" +/// ], +/// "properties": { +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "unknown" +/// ] +/// } +/// } +/// } +/// ] +///} +/// ``` +///
+#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)] +#[serde(tag = "kind")] +pub enum StepEventKindForGenericSpec { + #[serde(rename = "no_steps_defined")] + NoStepsDefined, + /**Execution was started. + +This is an initial event -- it is always expected to be the first event received from the event stream.*/ + #[serde(rename = "execution_started")] + ExecutionStarted { + ///A list of components, along with the number of items each component has. + components: ::std::vec::Vec, + ///Information about the first step. + first_step: StepInfoWithMetadataForGenericSpec, + ///The list of steps that will be executed. + steps: ::std::vec::Vec, + }, + ///Progress was reset along an attempt, and this attempt is going down a different path. + #[serde(rename = "progress_reset")] + ProgressReset { + ///The current attempt number. + attempt: u32, + ///The amount of time this attempt has taken so far. + attempt_elapsed: Duration, + ///A message associated with the reset. + message: ::std::string::String, + ///Progress-related metadata associated with this attempt. + metadata: ::serde_json::Value, + ///Information about the step. + step: StepInfoWithMetadataForGenericSpec, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + ///An attempt failed and this step is being retried. + #[serde(rename = "attempt_retry")] + AttemptRetry { + ///The amount of time the previous attempt took. + attempt_elapsed: Duration, + ///A message associated with the retry. + message: ::std::string::String, + ///The attempt number for the next attempt. + next_attempt: u32, + ///Information about the step. + step: StepInfoWithMetadataForGenericSpec, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + ///A step is complete and the next step has been started. + #[serde(rename = "step_completed")] + StepCompleted { + ///The attempt number that completed. + attempt: u32, + ///The time it took for this attempt to complete. + attempt_elapsed: Duration, + ///The next step that is being started. + next_step: StepInfoWithMetadataForGenericSpec, + ///The outcome of the step. + outcome: StepOutcomeForGenericSpec, + ///Information about the step that just completed. + step: StepInfoWithMetadataForGenericSpec, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + /**Execution is complete. + +This is a terminal event: it is guaranteed that no more events will be seen after this one.*/ + #[serde(rename = "execution_completed")] + ExecutionCompleted { + ///The time it took for this attempt to complete. + attempt_elapsed: Duration, + ///The attempt number that completed. + last_attempt: u32, + ///The outcome of the last step. + last_outcome: StepOutcomeForGenericSpec, + ///Information about the last step that completed. + last_step: StepInfoWithMetadataForGenericSpec, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + /**Execution failed. + +This is a terminal event: it is guaranteed that no more events will be seen after this one.*/ + #[serde(rename = "execution_failed")] + ExecutionFailed { + ///The time it took for this attempt to complete. + attempt_elapsed: Duration, + ///A chain of causes associated with the failure. + causes: ::std::vec::Vec<::std::string::String>, + ///Information about the step that failed. + failed_step: StepInfoWithMetadataForGenericSpec, + ///A message associated with the failure. + message: ::std::string::String, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + ///The total number of attempts that were performed before the step failed. + total_attempts: u32, + }, + /**Execution aborted by an external user. + +This is a terminal event: it is guaranteed that no more events will be seen after this one.*/ + #[serde(rename = "execution_aborted")] + ExecutionAborted { + ///Information about the step that was running at the time execution was aborted. + aborted_step: StepInfoWithMetadataForGenericSpec, + ///The attempt that was running at the time the step was aborted. + attempt: u32, + ///The time it took for this attempt to complete. + attempt_elapsed: Duration, + ///A message associated with the abort. + message: ::std::string::String, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + ///A nested step event occurred. + #[serde(rename = "nested")] + Nested { + ///The current attempt number. + attempt: u32, + ///The time it took for this attempt to complete. + attempt_elapsed: Duration, + ///The event that occurred. + event: ::oxide_update_engine_types::events::StepEvent< + ::oxide_update_engine_types::spec::GenericSpec, + >, + ///Information about the step that's occurring. + step: StepInfoWithMetadataForGenericSpec, + ///Total time elapsed since the start of the step. Includes prior attempts. + step_elapsed: Duration, + }, + #[serde(rename = "unknown")] + Unknown, +} +///Serializable information about a step. +/// +///
JSON schema +/// +/// ```json +///{ +/// "description": "Serializable information about a step.", +/// "type": "object", +/// "required": [ +/// "component", +/// "component_index", +/// "description", +/// "id", +/// "index", +/// "total_component_steps" +/// ], +/// "properties": { +/// "component": { +/// "description": "The component that this step is part of." +/// }, +/// "component_index": { +/// "description": "The index of the step within the component.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "description": { +/// "description": "The description for this step.", +/// "type": "string" +/// }, +/// "id": { +/// "description": "An identifier for this step." +/// }, +/// "index": { +/// "description": "The index of the step within all steps to be executed.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "total_component_steps": { +/// "description": "The total number of steps in this component.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// } +/// } +///} +/// ``` +///
+#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)] +pub struct StepInfoForExternalSpec { + ///The component that this step is part of. + pub component: ::serde_json::Value, + ///The index of the step within the component. + pub component_index: u32, + ///The description for this step. + pub description: ::std::string::String, + ///An identifier for this step. + pub id: ::serde_json::Value, + ///The index of the step within all steps to be executed. + pub index: u32, + ///The total number of steps in this component. + pub total_component_steps: u32, +} +///Serializable information about a step. +/// +///
JSON schema +/// +/// ```json +///{ +/// "description": "Serializable information about a step.", +/// "type": "object", +/// "required": [ +/// "component", +/// "component_index", +/// "description", +/// "id", +/// "index", +/// "total_component_steps" +/// ], +/// "properties": { +/// "component": { +/// "description": "The component that this step is part of." +/// }, +/// "component_index": { +/// "description": "The index of the step within the component.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "description": { +/// "description": "The description for this step.", +/// "type": "string" +/// }, +/// "id": { +/// "description": "An identifier for this step." +/// }, +/// "index": { +/// "description": "The index of the step within all steps to be executed.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// }, +/// "total_component_steps": { +/// "description": "The total number of steps in this component.", +/// "type": "integer", +/// "format": "uint", +/// "minimum": 0.0 +/// } +/// } +///} +/// ``` +///
+#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)] +pub struct StepInfoForGenericSpec { + ///The component that this step is part of. + pub component: ::serde_json::Value, + ///The index of the step within the component. + pub component_index: u32, + ///The description for this step. + pub description: ::std::string::String, + ///An identifier for this step. + pub id: ::serde_json::Value, + ///The index of the step within all steps to be executed. + pub index: u32, + ///The total number of steps in this component. + pub total_component_steps: u32, +} +///Serializable information about a step. +/// +///
JSON schema +/// +/// ```json +///{ +/// "description": "Serializable information about a step.", +/// "type": "object", +/// "required": [ +/// "info" +/// ], +/// "properties": { +/// "info": { +/// "description": "Information about this step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoForExternalSpec" +/// } +/// ] +/// }, +/// "metadata": { +/// "description": "Additional metadata associated with this step." +/// } +/// } +///} +/// ``` +///
+#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)] +pub struct StepInfoWithMetadataForExternalSpec { + ///Information about this step. + pub info: StepInfoForExternalSpec, + ///Additional metadata associated with this step. + #[serde(default, skip_serializing_if = "::std::option::Option::is_none")] + pub metadata: ::std::option::Option<::serde_json::Value>, +} +///Serializable information about a step. +/// +///
JSON schema +/// +/// ```json +///{ +/// "description": "Serializable information about a step.", +/// "type": "object", +/// "required": [ +/// "info" +/// ], +/// "properties": { +/// "info": { +/// "description": "Information about this step.", +/// "allOf": [ +/// { +/// "$ref": "#/definitions/StepInfoForGenericSpec" +/// } +/// ] +/// }, +/// "metadata": { +/// "description": "Additional metadata associated with this step." +/// } +/// } +///} +/// ``` +///
+#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)] +pub struct StepInfoWithMetadataForGenericSpec { + ///Information about this step. + pub info: StepInfoForGenericSpec, + ///Additional metadata associated with this step. + #[serde(default, skip_serializing_if = "::std::option::Option::is_none")] + pub metadata: ::std::option::Option<::serde_json::Value>, +} +///`StepOutcomeForExternalSpec` +/// +///
JSON schema +/// +/// ```json +///{ +/// "oneOf": [ +/// { +/// "description": "The step completed successfully.", +/// "type": "object", +/// "required": [ +/// "kind" +/// ], +/// "properties": { +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "success" +/// ] +/// }, +/// "message": { +/// "description": "An optional message associated with this step.", +/// "type": [ +/// "string", +/// "null" +/// ] +/// }, +/// "metadata": { +/// "description": "Optional completion metadata associated with the step." +/// } +/// } +/// }, +/// { +/// "description": "The step completed with a warning.", +/// "type": "object", +/// "required": [ +/// "kind", +/// "message" +/// ], +/// "properties": { +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "warning" +/// ] +/// }, +/// "message": { +/// "description": "A warning message.", +/// "type": "string" +/// }, +/// "metadata": { +/// "description": "Optional completion metadata associated with the step." +/// } +/// } +/// }, +/// { +/// "description": "The step was skipped with a message.", +/// "type": "object", +/// "required": [ +/// "kind", +/// "message" +/// ], +/// "properties": { +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "skipped" +/// ] +/// }, +/// "message": { +/// "description": "Message associated with the skip.", +/// "type": "string" +/// }, +/// "metadata": { +/// "description": "Optional metadata associated with the skip." +/// } +/// } +/// } +/// ] +///} +/// ``` +///
+#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)] +#[serde(tag = "kind")] +pub enum StepOutcomeForExternalSpec { + ///The step completed successfully. + #[serde(rename = "success")] + Success { + ///An optional message associated with this step. + #[serde(default, skip_serializing_if = "::std::option::Option::is_none")] + message: ::std::option::Option<::std::string::String>, + ///Optional completion metadata associated with the step. + #[serde(default, skip_serializing_if = "::std::option::Option::is_none")] + metadata: ::std::option::Option<::serde_json::Value>, + }, + ///The step completed with a warning. + #[serde(rename = "warning")] + Warning { + ///A warning message. + message: ::std::string::String, + ///Optional completion metadata associated with the step. + #[serde(default, skip_serializing_if = "::std::option::Option::is_none")] + metadata: ::std::option::Option<::serde_json::Value>, + }, + ///The step was skipped with a message. + #[serde(rename = "skipped")] + Skipped { + ///Message associated with the skip. + message: ::std::string::String, + ///Optional metadata associated with the skip. + #[serde(default, skip_serializing_if = "::std::option::Option::is_none")] + metadata: ::std::option::Option<::serde_json::Value>, + }, +} +///`StepOutcomeForGenericSpec` +/// +///
JSON schema +/// +/// ```json +///{ +/// "oneOf": [ +/// { +/// "description": "The step completed successfully.", +/// "type": "object", +/// "required": [ +/// "kind" +/// ], +/// "properties": { +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "success" +/// ] +/// }, +/// "message": { +/// "description": "An optional message associated with this step.", +/// "type": [ +/// "string", +/// "null" +/// ] +/// }, +/// "metadata": { +/// "description": "Optional completion metadata associated with the step." +/// } +/// } +/// }, +/// { +/// "description": "The step completed with a warning.", +/// "type": "object", +/// "required": [ +/// "kind", +/// "message" +/// ], +/// "properties": { +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "warning" +/// ] +/// }, +/// "message": { +/// "description": "A warning message.", +/// "type": "string" +/// }, +/// "metadata": { +/// "description": "Optional completion metadata associated with the step." +/// } +/// } +/// }, +/// { +/// "description": "The step was skipped with a message.", +/// "type": "object", +/// "required": [ +/// "kind", +/// "message" +/// ], +/// "properties": { +/// "kind": { +/// "type": "string", +/// "enum": [ +/// "skipped" +/// ] +/// }, +/// "message": { +/// "description": "Message associated with the skip.", +/// "type": "string" +/// }, +/// "metadata": { +/// "description": "Optional metadata associated with the skip." +/// } +/// } +/// } +/// ] +///} +/// ``` +///
+#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)] +#[serde(tag = "kind")] +pub enum StepOutcomeForGenericSpec { + ///The step completed successfully. + #[serde(rename = "success")] + Success { + ///An optional message associated with this step. + #[serde(default, skip_serializing_if = "::std::option::Option::is_none")] + message: ::std::option::Option<::std::string::String>, + ///Optional completion metadata associated with the step. + #[serde(default, skip_serializing_if = "::std::option::Option::is_none")] + metadata: ::std::option::Option<::serde_json::Value>, + }, + ///The step completed with a warning. + #[serde(rename = "warning")] + Warning { + ///A warning message. + message: ::std::string::String, + ///Optional completion metadata associated with the step. + #[serde(default, skip_serializing_if = "::std::option::Option::is_none")] + metadata: ::std::option::Option<::serde_json::Value>, + }, + ///The step was skipped with a message. + #[serde(rename = "skipped")] + Skipped { + ///Message associated with the skip. + message: ::std::string::String, + ///Optional metadata associated with the skip. + #[serde(default, skip_serializing_if = "::std::option::Option::is_none")] + metadata: ::std::option::Option<::serde_json::Value>, + }, +}