use serde::{Deserialize, Serialize};
use serde_json::Value;
pub const VALID_OPERATIONS: &[&str] = &["create", "update", "complete", "read"];
pub const UCP_ANNOTATIONS: &[&str] = &["ucp_request", "ucp_response"];
pub fn json_type_name(value: &Value) -> &'static str {
match value {
Value::Null => "null",
Value::Bool(_) => "boolean",
Value::Number(_) => "number",
Value::String(_) => "string",
Value::Array(_) => "array",
Value::Object(_) => "object",
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Direction {
Request,
Response,
}
impl Direction {
pub fn annotation_key(&self) -> &'static str {
match self {
Direction::Request => "ucp_request",
Direction::Response => "ucp_response",
}
}
pub fn from_request_flag(is_request: bool) -> Self {
if is_request {
Direction::Request
} else {
Direction::Response
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum Visibility {
#[default]
Include,
Omit,
Required,
Optional,
}
impl Visibility {
pub fn parse(s: &str) -> Option<Self> {
match s {
"omit" => Some(Visibility::Omit),
"required" => Some(Visibility::Required),
"optional" => Some(Visibility::Optional),
_ => None,
}
}
}
#[derive(Debug, Clone)]
pub struct ResolveOptions {
pub direction: Direction,
pub operation: String,
pub strict: bool,
}
impl ResolveOptions {
pub fn new(direction: Direction, operation: impl Into<String>) -> Self {
Self {
direction,
operation: operation.into().to_lowercase(),
strict: false,
}
}
pub fn strict(mut self, strict: bool) -> Self {
self.strict = strict;
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn direction_annotation_key() {
assert_eq!(Direction::Request.annotation_key(), "ucp_request");
assert_eq!(Direction::Response.annotation_key(), "ucp_response");
}
#[test]
fn visibility_parse_valid() {
assert_eq!(Visibility::parse("omit"), Some(Visibility::Omit));
assert_eq!(Visibility::parse("required"), Some(Visibility::Required));
assert_eq!(Visibility::parse("optional"), Some(Visibility::Optional));
}
#[test]
fn visibility_parse_invalid() {
assert_eq!(Visibility::parse("include"), None);
assert_eq!(Visibility::parse("readonly"), None);
assert_eq!(Visibility::parse(""), None);
}
#[test]
fn resolve_options_normalizes_operation() {
let opts = ResolveOptions::new(Direction::Request, "Create");
assert_eq!(opts.operation, "create");
let opts = ResolveOptions::new(Direction::Request, "UPDATE");
assert_eq!(opts.operation, "update");
}
}