use std::borrow::Cow;
use std::fmt;
use schemars::{JsonSchema, Schema, SchemaGenerator, json_schema};
use serde::{Deserialize, Serialize};
use crate::Error;
fn unit_interval_schema(name: &str) -> Schema {
json_schema!({
"type": "number",
"minimum": 0.0,
"maximum": 1.0,
"description": format!("{name} in the closed unit interval"),
})
}
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(try_from = "f64", into = "f64")]
pub struct Probability(f64);
impl Probability {
pub const fn get(self) -> f64 {
self.0
}
}
impl TryFrom<f64> for Probability {
type Error = Error;
fn try_from(value: f64) -> Result<Self, Error> {
if (0.0..=1.0).contains(&value) {
Ok(Self(value))
} else {
Err(Error::Protocol {
detail: format!("probability {value} is outside 0..=1"),
})
}
}
}
impl From<Probability> for f64 {
fn from(p: Probability) -> f64 {
p.0
}
}
impl JsonSchema for Probability {
fn schema_name() -> Cow<'static, str> {
"Probability".into()
}
fn json_schema(_: &mut SchemaGenerator) -> Schema {
unit_interval_schema("probability")
}
}
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(try_from = "f64", into = "f64")]
pub struct Confidence(f64);
impl Confidence {
pub const fn get(self) -> f64 {
self.0
}
}
impl TryFrom<f64> for Confidence {
type Error = Error;
fn try_from(value: f64) -> Result<Self, Error> {
if (0.0..=1.0).contains(&value) {
Ok(Self(value))
} else {
Err(Error::Protocol {
detail: format!("confidence {value} is outside 0..=1"),
})
}
}
}
impl From<Confidence> for f64 {
fn from(c: Confidence) -> f64 {
c.0
}
}
impl JsonSchema for Confidence {
fn schema_name() -> Cow<'static, str> {
"Confidence".into()
}
fn json_schema(_: &mut SchemaGenerator) -> Schema {
unit_interval_schema("confidence")
}
}
#[derive(Clone, PartialEq, Eq)]
pub struct ApiKey(String);
impl ApiKey {
pub(crate) fn expose(&self) -> &str {
&self.0
}
}
impl From<String> for ApiKey {
fn from(s: String) -> Self {
Self(s)
}
}
impl From<&str> for ApiKey {
fn from(s: &str) -> Self {
Self(s.to_owned())
}
}
impl fmt::Debug for ApiKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("ApiKey(***)")
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(transparent)]
pub struct Model(String);
impl Model {
pub fn latest() -> Self {
Self("jev-latest".to_owned())
}
pub fn preview() -> Self {
Self("jev-preview".to_owned())
}
pub fn new(id: impl Into<String>) -> Self {
Self(id.into())
}
pub fn as_str(&self) -> &str {
&self.0
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct State(pub(crate) Repr);
#[derive(Clone, Debug, PartialEq)]
pub(crate) enum Repr {
Ready(serde_json::Value),
Invalid(String),
}
impl State {
pub(crate) fn value(&self) -> Result<&serde_json::Value, Error> {
match &self.0 {
Repr::Ready(v) => Ok(v),
Repr::Invalid(detail) => Err(Error::Config {
detail: format!("state is not serialisable: {detail}"),
}),
}
}
}
impl<T: Serialize + ?Sized> From<&T> for State {
fn from(value: &T) -> Self {
Self(match serde_json::to_value(value) {
Ok(v) => Repr::Ready(v),
Err(e) => Repr::Invalid(e.to_string()),
})
}
}
impl From<String> for State {
fn from(text: String) -> Self {
Self(Repr::Ready(serde_json::Value::String(text)))
}
}
impl From<serde_json::Value> for State {
fn from(value: serde_json::Value) -> Self {
Self(Repr::Ready(value))
}
}
impl Serialize for State {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
match &self.0 {
Repr::Ready(v) => v.serialize(s),
Repr::Invalid(detail) => Err(serde::ser::Error::custom(detail)),
}
}
}
impl<'de> Deserialize<'de> for State {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
serde_json::Value::deserialize(d).map(|v| Self(Repr::Ready(v)))
}
}
impl JsonSchema for State {
fn schema_name() -> Cow<'static, str> {
"State".into()
}
fn json_schema(g: &mut SchemaGenerator) -> Schema {
<serde_json::Value as JsonSchema>::json_schema(g)
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(transparent)]
pub struct Instructions(pub(crate) serde_json::Value);
impl From<&str> for Instructions {
fn from(s: &str) -> Self {
Self(serde_json::Value::String(s.to_owned()))
}
}
impl From<String> for Instructions {
fn from(s: String) -> Self {
Self(serde_json::Value::String(s))
}
}
impl From<serde_json::Value> for Instructions {
fn from(v: serde_json::Value) -> Self {
Self(v)
}
}