style: rustfmt squad host + adapter files
Formatting-only. Runs the project formatter over the files authored/edited this session (host lib+tests, adapter item/squad_ext/squad_projection/mod + projection test). The intentionally-preserved dirty catalog.rs and pre-existing /club-era host drift beyond these files are out of scope.
This commit is contained in:
+165
-39
@@ -164,8 +164,14 @@ pub struct CoreSquadSlot {
|
||||
/// when Stale — the host decides policy).
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum CoreExtState {
|
||||
Fresh { schema_version: i64, payload: String },
|
||||
Stale { schema_version: i64, payload: String },
|
||||
Fresh {
|
||||
schema_version: i64,
|
||||
payload: String,
|
||||
},
|
||||
Stale {
|
||||
schema_version: i64,
|
||||
payload: String,
|
||||
},
|
||||
Missing,
|
||||
}
|
||||
|
||||
@@ -299,7 +305,11 @@ impl CoreAccess for HttpCoreClient {
|
||||
}
|
||||
let v: Value = resp.json().map_err(|e| CoreError::Parse(e.to_string()))?;
|
||||
Ok(CoreReplaceResult {
|
||||
squad_id: v.get("squad_id").and_then(|x| x.as_str()).unwrap_or("").to_string(),
|
||||
squad_id: v
|
||||
.get("squad_id")
|
||||
.and_then(|x| x.as_str())
|
||||
.unwrap_or("")
|
||||
.to_string(),
|
||||
canonical_fingerprint: v
|
||||
.get("canonical_fingerprint")
|
||||
.and_then(|x| x.as_str())
|
||||
@@ -343,8 +353,14 @@ pub fn replace_request_body(req: &CoreReplaceRequest) -> Value {
|
||||
|
||||
/// Parse Core's `GET /squad/ext` response into a [`CoreSquadRead`].
|
||||
pub fn parse_core_squad_read(v: &Value) -> Result<CoreSquadRead, CoreError> {
|
||||
let squad = v.get("squad").ok_or_else(|| CoreError::Parse("missing `squad`".into()))?;
|
||||
let name = squad.get("name").and_then(|x| x.as_str()).unwrap_or("").to_string();
|
||||
let squad = v
|
||||
.get("squad")
|
||||
.ok_or_else(|| CoreError::Parse("missing `squad`".into()))?;
|
||||
let name = squad
|
||||
.get("name")
|
||||
.and_then(|x| x.as_str())
|
||||
.unwrap_or("")
|
||||
.to_string();
|
||||
let formation = squad
|
||||
.get("formation")
|
||||
.and_then(|x| x.as_str())
|
||||
@@ -360,25 +376,56 @@ pub fn parse_core_squad_read(v: &Value) -> Result<CoreSquadRead, CoreError> {
|
||||
Some(CoreSquadSlot {
|
||||
owned_card_id: p.get("owned_card_id")?.as_str()?.to_string(),
|
||||
index: p.get("position_index")?.as_i64()?,
|
||||
is_captain: p.get("is_captain").and_then(|x| x.as_bool()).unwrap_or(false),
|
||||
is_on_bench: p.get("is_on_bench").and_then(|x| x.as_bool()).unwrap_or(false),
|
||||
is_captain: p
|
||||
.get("is_captain")
|
||||
.and_then(|x| x.as_bool())
|
||||
.unwrap_or(false),
|
||||
is_on_bench: p
|
||||
.get("is_on_bench")
|
||||
.and_then(|x| x.as_bool())
|
||||
.unwrap_or(false),
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
let ext_v = v.get("extension").ok_or_else(|| CoreError::Parse("missing `extension`".into()))?;
|
||||
let ext_v = v
|
||||
.get("extension")
|
||||
.ok_or_else(|| CoreError::Parse("missing `extension`".into()))?;
|
||||
let ext = match ext_v.get("state").and_then(|x| x.as_str()) {
|
||||
Some("fresh") => CoreExtState::Fresh {
|
||||
schema_version: ext_v.get("schema_version").and_then(|x| x.as_i64()).unwrap_or(0),
|
||||
payload: ext_v.get("payload").and_then(|x| x.as_str()).unwrap_or("").to_string(),
|
||||
schema_version: ext_v
|
||||
.get("schema_version")
|
||||
.and_then(|x| x.as_i64())
|
||||
.unwrap_or(0),
|
||||
payload: ext_v
|
||||
.get("payload")
|
||||
.and_then(|x| x.as_str())
|
||||
.unwrap_or("")
|
||||
.to_string(),
|
||||
},
|
||||
Some("stale") => CoreExtState::Stale {
|
||||
schema_version: ext_v.get("schema_version").and_then(|x| x.as_i64()).unwrap_or(0),
|
||||
payload: ext_v.get("payload").and_then(|x| x.as_str()).unwrap_or("").to_string(),
|
||||
schema_version: ext_v
|
||||
.get("schema_version")
|
||||
.and_then(|x| x.as_i64())
|
||||
.unwrap_or(0),
|
||||
payload: ext_v
|
||||
.get("payload")
|
||||
.and_then(|x| x.as_str())
|
||||
.unwrap_or("")
|
||||
.to_string(),
|
||||
},
|
||||
Some("missing") => CoreExtState::Missing,
|
||||
other => return Err(CoreError::Parse(format!("unknown extension state {other:?}"))),
|
||||
other => {
|
||||
return Err(CoreError::Parse(format!(
|
||||
"unknown extension state {other:?}"
|
||||
)))
|
||||
}
|
||||
};
|
||||
Ok(CoreSquadRead { name, formation, slots, ext })
|
||||
Ok(CoreSquadRead {
|
||||
name,
|
||||
formation,
|
||||
slots,
|
||||
ext,
|
||||
})
|
||||
}
|
||||
|
||||
/// Parse Core's `/collection` response `{ "collection": [...], "total": n }` into
|
||||
@@ -655,7 +702,10 @@ fn project_active_squad(deps: &SquadDeps<'_>) -> HostProjection {
|
||||
Err(e) => return HostProjection::Error(e.to_string()),
|
||||
};
|
||||
let ext = match &read.ext {
|
||||
CoreExtState::Fresh { schema_version, payload } => {
|
||||
CoreExtState::Fresh {
|
||||
schema_version,
|
||||
payload,
|
||||
} => {
|
||||
match Fifa17SquadExtensionV1::from_payload(*schema_version, payload) {
|
||||
Ok(e) => e,
|
||||
// Fresh but the payload does not parse as our schema: corruption,
|
||||
@@ -670,8 +720,10 @@ fn project_active_squad(deps: &SquadDeps<'_>) -> HostProjection {
|
||||
Ok(v) => v,
|
||||
Err(e) => return HostProjection::Error(e.to_string()),
|
||||
};
|
||||
let owned_by_id: std::collections::HashMap<String, CoreOwnedItem> =
|
||||
owned.into_iter().map(|i| (i.owned_card_id.clone(), i)).collect();
|
||||
let owned_by_id: std::collections::HashMap<String, CoreOwnedItem> = owned
|
||||
.into_iter()
|
||||
.map(|i| (i.owned_card_id.clone(), i))
|
||||
.collect();
|
||||
let slots: Vec<ProjectionSlot> = read
|
||||
.slots
|
||||
.iter()
|
||||
@@ -718,7 +770,10 @@ pub fn handle_put_squad(body: &[u8], deps: &SquadDeps<'_>) -> (WireResponse, Squ
|
||||
Err(e) => {
|
||||
return (
|
||||
error_response(400, "parse_error"),
|
||||
SquadLog { outcome: "parse_error", detail: e.to_string() },
|
||||
SquadLog {
|
||||
outcome: "parse_error",
|
||||
detail: e.to_string(),
|
||||
},
|
||||
)
|
||||
}
|
||||
};
|
||||
@@ -729,13 +784,19 @@ pub fn handle_put_squad(body: &[u8], deps: &SquadDeps<'_>) -> (WireResponse, Squ
|
||||
Err(SquadBuildError::UnresolvedWireIds(ids)) => {
|
||||
return (
|
||||
error_response(400, "unresolved_wire_ids"),
|
||||
SquadLog { outcome: "unresolved_wire_ids", detail: format!("{ids:?}") },
|
||||
SquadLog {
|
||||
outcome: "unresolved_wire_ids",
|
||||
detail: format!("{ids:?}"),
|
||||
},
|
||||
)
|
||||
}
|
||||
Err(SquadBuildError::DuplicateOwnedItem(id)) => {
|
||||
return (
|
||||
error_response(400, "duplicate_owned_item"),
|
||||
SquadLog { outcome: "duplicate_owned_item", detail: id },
|
||||
SquadLog {
|
||||
outcome: "duplicate_owned_item",
|
||||
detail: id,
|
||||
},
|
||||
)
|
||||
}
|
||||
};
|
||||
@@ -747,7 +808,10 @@ pub fn handle_put_squad(body: &[u8], deps: &SquadDeps<'_>) -> (WireResponse, Squ
|
||||
Err(e) => {
|
||||
return (
|
||||
error_response(502, "core_error"),
|
||||
SquadLog { outcome: "core_error", detail: e.to_string() },
|
||||
SquadLog {
|
||||
outcome: "core_error",
|
||||
detail: e.to_string(),
|
||||
},
|
||||
)
|
||||
}
|
||||
};
|
||||
@@ -755,7 +819,10 @@ pub fn handle_put_squad(body: &[u8], deps: &SquadDeps<'_>) -> (WireResponse, Squ
|
||||
if !owned_set.contains(&slot.owned_card_id) {
|
||||
return (
|
||||
error_response(403, "not_owned"),
|
||||
SquadLog { outcome: "unauthorized_item", detail: slot.owned_card_id.clone() },
|
||||
SquadLog {
|
||||
outcome: "unauthorized_item",
|
||||
detail: slot.owned_card_id.clone(),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -786,11 +853,17 @@ pub fn handle_put_squad(body: &[u8], deps: &SquadDeps<'_>) -> (WireResponse, Squ
|
||||
match deps.core.replace_squad(&req) {
|
||||
Ok(_) => (
|
||||
json_response(&save_ack(put.id)),
|
||||
SquadLog { outcome: "ok", detail: String::new() },
|
||||
SquadLog {
|
||||
outcome: "ok",
|
||||
detail: String::new(),
|
||||
},
|
||||
),
|
||||
Err(e) => (
|
||||
error_response(502, "core_error"),
|
||||
SquadLog { outcome: "core_error", detail: e.to_string() },
|
||||
SquadLog {
|
||||
outcome: "core_error",
|
||||
detail: e.to_string(),
|
||||
},
|
||||
),
|
||||
}
|
||||
}
|
||||
@@ -802,19 +875,31 @@ pub fn handle_squad_list(deps: &SquadDeps<'_>) -> (WireResponse, SquadLog) {
|
||||
match project_active_squad(deps) {
|
||||
HostProjection::Squad(v) => (
|
||||
json_response(&squad_list(&v)),
|
||||
SquadLog { outcome: "ok", detail: String::new() },
|
||||
SquadLog {
|
||||
outcome: "ok",
|
||||
detail: String::new(),
|
||||
},
|
||||
),
|
||||
HostProjection::Stale => (
|
||||
json_response(&json!({ "squad": [] })),
|
||||
SquadLog { outcome: "stale_integrity", detail: "stale extension not applied".into() },
|
||||
SquadLog {
|
||||
outcome: "stale_integrity",
|
||||
detail: "stale extension not applied".into(),
|
||||
},
|
||||
),
|
||||
HostProjection::Missing => (
|
||||
json_response(&json!({ "squad": [] })),
|
||||
SquadLog { outcome: "missing_integrity", detail: "no extension stored".into() },
|
||||
SquadLog {
|
||||
outcome: "missing_integrity",
|
||||
detail: "no extension stored".into(),
|
||||
},
|
||||
),
|
||||
HostProjection::Error(e) => (
|
||||
json_response(&json!({ "squad": [] })),
|
||||
SquadLog { outcome: "core_error", detail: e },
|
||||
SquadLog {
|
||||
outcome: "core_error",
|
||||
detail: e,
|
||||
},
|
||||
),
|
||||
}
|
||||
}
|
||||
@@ -841,8 +926,10 @@ fn set_json_body(resp: &mut WireResponse, body: Vec<u8>) {
|
||||
&& !k.eq_ignore_ascii_case("content-type")
|
||||
&& !k.eq_ignore_ascii_case("transfer-encoding")
|
||||
});
|
||||
resp.headers.push(("Content-Type".to_string(), "application/json".to_string()));
|
||||
resp.headers.push(("Content-Length".to_string(), body.len().to_string()));
|
||||
resp.headers
|
||||
.push(("Content-Type".to_string(), "application/json".to_string()));
|
||||
resp.headers
|
||||
.push(("Content-Length".to_string(), body.len().to_string()));
|
||||
resp.body = body;
|
||||
}
|
||||
|
||||
@@ -862,44 +949,83 @@ pub fn handle_user_mass_info(
|
||||
Err(e) => {
|
||||
return (
|
||||
error_response(502, "upstream_unavailable"),
|
||||
SquadLog { outcome: "python_unreachable", detail: e.to_string() },
|
||||
SquadLog {
|
||||
outcome: "python_unreachable",
|
||||
detail: e.to_string(),
|
||||
},
|
||||
)
|
||||
}
|
||||
};
|
||||
// Only a successful JSON object carrying `.squad` is overlaid; anything else
|
||||
// is returned verbatim (we never invent a squad into an unrelated response).
|
||||
if !(200..300).contains(&resp.status) {
|
||||
return (resp, SquadLog { outcome: "python_non_2xx_passthrough", detail: String::new() });
|
||||
return (
|
||||
resp,
|
||||
SquadLog {
|
||||
outcome: "python_non_2xx_passthrough",
|
||||
detail: String::new(),
|
||||
},
|
||||
);
|
||||
}
|
||||
let mut root: Value = match serde_json::from_slice::<Value>(&resp.body) {
|
||||
Ok(v) if v.is_object() => v,
|
||||
_ => return (resp, SquadLog { outcome: "python_body_unusable_passthrough", detail: String::new() }),
|
||||
_ => {
|
||||
return (
|
||||
resp,
|
||||
SquadLog {
|
||||
outcome: "python_body_unusable_passthrough",
|
||||
detail: String::new(),
|
||||
},
|
||||
)
|
||||
}
|
||||
};
|
||||
if root.get("squad").is_none() {
|
||||
return (resp, SquadLog { outcome: "python_no_squad_passthrough", detail: String::new() });
|
||||
return (
|
||||
resp,
|
||||
SquadLog {
|
||||
outcome: "python_no_squad_passthrough",
|
||||
detail: String::new(),
|
||||
},
|
||||
);
|
||||
}
|
||||
// Preserve the client's persona from Python's own response.
|
||||
let persona = root["squad"]
|
||||
.get("personaId")
|
||||
.and_then(|x| x.as_i64())
|
||||
.or_else(|| root.get("userInfo").and_then(|u| u.get("personaId")).and_then(|x| x.as_i64()))
|
||||
.or_else(|| {
|
||||
root.get("userInfo")
|
||||
.and_then(|u| u.get("personaId"))
|
||||
.and_then(|x| x.as_i64())
|
||||
})
|
||||
.unwrap_or(0);
|
||||
let (squad_val, log) = match project_active_squad(deps) {
|
||||
HostProjection::Squad(v) => (
|
||||
user_mass_info_squad(v, persona),
|
||||
SquadLog { outcome: "ok", detail: String::new() },
|
||||
SquadLog {
|
||||
outcome: "ok",
|
||||
detail: String::new(),
|
||||
},
|
||||
),
|
||||
HostProjection::Stale => (
|
||||
empty_squad_overlay(persona),
|
||||
SquadLog { outcome: "stale_integrity", detail: "stale extension not applied".into() },
|
||||
SquadLog {
|
||||
outcome: "stale_integrity",
|
||||
detail: "stale extension not applied".into(),
|
||||
},
|
||||
),
|
||||
HostProjection::Missing => (
|
||||
empty_squad_overlay(persona),
|
||||
SquadLog { outcome: "missing_integrity", detail: "no extension stored".into() },
|
||||
SquadLog {
|
||||
outcome: "missing_integrity",
|
||||
detail: "no extension stored".into(),
|
||||
},
|
||||
),
|
||||
HostProjection::Error(e) => (
|
||||
empty_squad_overlay(persona),
|
||||
SquadLog { outcome: "core_error", detail: e },
|
||||
SquadLog {
|
||||
outcome: "core_error",
|
||||
detail: e,
|
||||
},
|
||||
),
|
||||
};
|
||||
root["squad"] = squad_val;
|
||||
|
||||
Reference in New Issue
Block a user