use std::fmt::Display;
use hashbrown::{HashMap, HashSet};
use serde::ser::SerializeSeq as _;
use serde::{Serialize, Serializer};
#[expect(clippy::ref_option, reason = "Serde API")]
fn single_to_string_array<S, T>(v: &Option<T>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: Display,
{
match *v {
Some(ref value) => {
let mut seq = serializer.serialize_seq(Some(1))?;
seq.serialize_element(&value.to_string())?;
seq.end()
},
None => serializer.serialize_none(),
}
}
#[expect(clippy::ref_option, reason = "Serde API")]
fn multiple_to_string_array<S, T, U>(value: &Option<T>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
for<'a> &'a T: IntoIterator<Item = &'a U>,
U: Display,
{
match *value {
Some(ref iter) => {
let iter = iter.into_iter();
let (_lower, upper) = iter.size_hint();
let mut seq = serializer.serialize_seq(upper)?;
for next in iter {
seq.serialize_element(&next.to_string())?;
}
seq.end()
},
None => serializer.serialize_none(),
}
}
#[expect(clippy::ref_option, reason = "Serde API")]
fn serialize_labels<S, T, U>(
value: &Option<HashMap<T, Option<U>>>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: Display,
U: Display,
{
match *value {
Some(ref iter) => {
let iter = iter.into_iter();
let (_lower, upper) = iter.size_hint();
let mut seq = serializer.serialize_seq(upper)?;
for (key, value) in iter {
if let Some(ref value) = *value {
seq.serialize_element(&format!("{}={}", key, value))?;
} else {
seq.serialize_element(&key.to_string())?;
}
}
seq.end()
},
None => serializer.serialize_none(),
}
}
pub enum Status {
Created,
Restarting,
Running,
Removing,
Paused,
Exited,
Dead,
}
impl std::fmt::Display for Status {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match *self {
Status::Created => "created",
Status::Restarting => "restarting",
Status::Running => "running",
Status::Removing => "removing",
Status::Paused => "paused",
Status::Exited => "exited",
Status::Dead => "dead",
};
f.write_str(s)
}
}
#[derive(Eq, PartialEq, Hash, Debug)]
pub enum Health {
Starting,
Healthy,
Unhealthy,
None,
}
impl std::fmt::Display for Health {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match *self {
Health::Starting => "starting",
Health::Healthy => "healthy",
Health::Unhealthy => "unhealthy",
Health::None => "none",
};
f.write_str(s)
}
}
#[derive(Serialize, Default)]
pub struct Filters {
#[serde(
serialize_with = "single_to_string_array",
skip_serializing_if = "Option::is_none"
)]
pub is_task: Option<bool>,
#[serde(
serialize_with = "multiple_to_string_array",
skip_serializing_if = "Option::is_none"
)]
pub status: Option<HashSet<Status>>,
#[serde(
serialize_with = "multiple_to_string_array",
skip_serializing_if = "Option::is_none"
)]
pub exited: Option<HashSet<i32>>,
#[serde(
serialize_with = "serialize_labels",
skip_serializing_if = "Option::is_none"
)]
pub label: Option<HashMap<Box<str>, Option<Box<str>>>>,
#[serde(
serialize_with = "multiple_to_string_array",
skip_serializing_if = "Option::is_none"
)]
pub health: Option<HashSet<Health>>,
#[serde(
serialize_with = "multiple_to_string_array",
skip_serializing_if = "Option::is_none"
)]
pub name: Option<HashSet<Box<str>>>,
#[serde(
serialize_with = "multiple_to_string_array",
skip_serializing_if = "Option::is_none"
)]
pub id: Option<HashSet<Box<str>>>,
#[serde(
serialize_with = "multiple_to_string_array",
skip_serializing_if = "Option::is_none"
)]
pub volume: Option<HashSet<Box<str>>>,
#[serde(
serialize_with = "multiple_to_string_array",
skip_serializing_if = "Option::is_none"
)]
pub network: Option<HashSet<Box<str>>>,
#[serde(
serialize_with = "multiple_to_string_array",
skip_serializing_if = "Option::is_none"
)]
pub ancestor: Option<HashSet<Box<str>>>,
#[serde(
serialize_with = "single_to_string_array",
skip_serializing_if = "Option::is_none"
)]
pub before: Option<Box<str>>,
#[serde(
serialize_with = "single_to_string_array",
skip_serializing_if = "Option::is_none"
)]
pub since: Option<Box<str>>,
#[serde(
serialize_with = "multiple_to_string_array",
skip_serializing_if = "Option::is_none"
)]
pub publish: Option<HashSet<Box<str>>>,
}