mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-04 19:15:57 +00:00
diagnostics.kernel takes a typed contract, as main's other diagnostics commands do
Its choice (solidcore or smlib) and its reply ({choice, environment}) get
schemas; a bad choice is refused with the handler's message.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DtL5M41G8Nua7HvuFPZkmJ
This commit is contained in:
@@ -60,7 +60,12 @@ pub static COMMANDS: &[CommandSpec] = &[
|
||||
inside it; total counts its outermost run only. Recording also starts with SOLIDCRAFT_PROFILE=1, the CLI's \
|
||||
--profile and the app's preference; off, it costs nothing measurable. Read-only",
|
||||
),
|
||||
CommandSpec::new("diagnostics.kernel", "Geometry Kernel", kernel).icon("bug_report").noundo().params(
|
||||
CommandSpec::new("diagnostics.kernel", "Geometry Kernel", crate::checked!("diagnostics.kernel", kernel))
|
||||
.icon("bug_report")
|
||||
.noundo()
|
||||
.contract(&KERNEL_CONTRACT)
|
||||
.output(output_schema_for::<crate::schema::diagnostics::KernelReply>)
|
||||
.params(
|
||||
"choice?: solidcore | smlib (sets which kernel answers every operation: solidcore, the default = the Rust port; \
|
||||
smlib = the C++ SMLib kernel, refused as not available on a build without it, such as the web app; bodies already \
|
||||
computed keep their results). SOLIDCRAFT_KERNEL, when set, wins over it. Returns {choice, environment}: choice is \
|
||||
@@ -96,7 +101,12 @@ fn kernel(_: &mut Session, p: &Value) -> Result<Value> {
|
||||
if let Some(v) = p.get("choice").filter(|v| !v.is_null()) {
|
||||
route::set_choice(kernel_asked(v, solidcraft_kernel::smlib_built())?);
|
||||
}
|
||||
Ok(json!({ "choice": route::choice().id(), "environment": route::overridden() }))
|
||||
use crate::schema::diagnostics::{KernelChoice, KernelReply};
|
||||
let choice = match route::choice() {
|
||||
route::Backend::Solidcore => KernelChoice::Solidcore,
|
||||
route::Backend::Smlib => KernelChoice::Smlib,
|
||||
};
|
||||
serde_json::to_value(KernelReply { choice, environment: route::overridden() }).map_err(|e| bad("diagnostics.kernel", e.to_string()))
|
||||
}
|
||||
|
||||
/// The kernel `choice` asks for, on a build that has (`built`) the C++ kernel or doesn't. A choice of
|
||||
@@ -172,6 +182,7 @@ fn crash_test(_: &mut Session, p: &Value) -> Result<Value> {
|
||||
|
||||
const PROFILE_CONTRACT: crate::schema::TypedContract<crate::schema::diagnostics::ProfileParams> = crate::schema::TypedContract::new();
|
||||
|
||||
const KERNEL_CONTRACT: crate::schema::TypedContract<crate::schema::diagnostics::KernelParams> = crate::schema::TypedContract::new();
|
||||
const VALIDATION_CONTRACT: crate::schema::TypedContract<crate::schema::diagnostics::ValidationParams> = crate::schema::TypedContract::new();
|
||||
|
||||
fn validation(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
|
||||
@@ -330,6 +330,44 @@ impl From<solidcraft_kernel::Validation> for ValidationMode {
|
||||
}
|
||||
}
|
||||
|
||||
/// Read, or set, which kernel answers every operation.
|
||||
#[derive(Debug, Default, Deserialize, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
pub struct KernelParams {
|
||||
/// The kernel to use from now on. Default: leave it as it is. `smlib` is refused on a build
|
||||
/// without the C++ kernel; `SOLIDCRAFT_KERNEL`, when set, wins over it.
|
||||
#[serde(default, deserialize_with = "kernel_choice")]
|
||||
pub choice: Option<KernelChoice>,
|
||||
}
|
||||
|
||||
/// A geometry kernel.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum KernelChoice {
|
||||
/// solidcore, the Rust port of SMLib (the default).
|
||||
Solidcore,
|
||||
/// The C++ SMLib kernel.
|
||||
Smlib,
|
||||
}
|
||||
|
||||
fn kernel_choice<'de, D: serde::Deserializer<'de>>(d: D) -> Result<Option<KernelChoice>, D::Error> {
|
||||
match Value::deserialize(d)? {
|
||||
Value::Null => Ok(None),
|
||||
Value::String(s) if s == "solidcore" => Ok(Some(KernelChoice::Solidcore)),
|
||||
Value::String(s) if s == "smlib" => Ok(Some(KernelChoice::Smlib)),
|
||||
_ => Err(serde::de::Error::custom(super::check::whole("`choice` is solidcore or smlib"))),
|
||||
}
|
||||
}
|
||||
|
||||
/// The reply of `diagnostics.kernel`.
|
||||
#[derive(Debug, Serialize, JsonSchema)]
|
||||
pub struct KernelReply {
|
||||
/// The kernel in force now.
|
||||
pub choice: KernelChoice,
|
||||
/// Whether `SOLIDCRAFT_KERNEL` chose it.
|
||||
pub environment: bool,
|
||||
}
|
||||
|
||||
/// Read, or set, when SMLib's full check runs on the features computed from now on.
|
||||
#[derive(Debug, Default, Deserialize, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
|
||||
@@ -2,7 +2,7 @@ use serde_json::{Value, json};
|
||||
|
||||
use super::{
|
||||
CrashReport, CrashReportList, CrashReportParams, CrashReportsClearParams, CrashReportsCleared, CrashReportsParams, CrashTestMode,
|
||||
CrashTestParams, ProfileParams, ValidationParams,
|
||||
CrashTestParams, KernelParams, ProfileParams, ValidationParams,
|
||||
};
|
||||
use crate::Session;
|
||||
use crate::schema::tests::{assert_keys, assert_strict_keeps_todays_errors, conforms};
|
||||
@@ -16,6 +16,7 @@ fn schemas_and_the_key_check_agree() {
|
||||
assert_keys(input_schema_for::<CrashTestParams>(), &["mode"]);
|
||||
assert_keys(input_schema_for::<ProfileParams>(), &["enabled", "reset", "top", "trace"]);
|
||||
assert_keys(input_schema_for::<ValidationParams>(), &["mode"]);
|
||||
assert_keys(input_schema_for::<KernelParams>(), &["choice"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -29,6 +30,8 @@ fn strict_keeps_todays_errors() {
|
||||
("diagnostics.profile", json!({"trace": 5})),
|
||||
("diagnostics.validation", json!({"mode": "each step"})),
|
||||
("diagnostics.validation", json!({"mode": true})),
|
||||
("diagnostics.kernel", json!({"choice": "cpp"})),
|
||||
("diagnostics.kernel", json!({"choice": 1})),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user