codex_protocol/
conversation_id.rs

1use std::fmt::Display;
2
3use std::borrow::Cow;
4use schemars::{JsonSchema, SchemaGenerator};
5use serde::Deserialize;
6use serde::Serialize;
7use ts_rs::TS;
8use uuid::Uuid;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, TS, Hash)]
11#[ts(type = "string")]
12pub struct ConversationId {
13    uuid: Uuid,
14}
15
16impl ConversationId {
17    pub fn new() -> Self {
18        Self {
19            uuid: Uuid::now_v7(),
20        }
21    }
22
23    pub fn from_string(s: &str) -> Result<Self, uuid::Error> {
24        Ok(Self {
25            uuid: Uuid::parse_str(s)?,
26        })
27    }
28}
29
30impl Default for ConversationId {
31    fn default() -> Self {
32        Self::new()
33    }
34}
35
36impl Display for ConversationId {
37    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38        write!(f, "{}", self.uuid)
39    }
40}
41
42impl Serialize for ConversationId {
43    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
44    where
45        S: serde::Serializer,
46    {
47        serializer.collect_str(&self.uuid)
48    }
49}
50
51impl<'de> Deserialize<'de> for ConversationId {
52    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
53    where
54        D: serde::Deserializer<'de>,
55    {
56        let value = String::deserialize(deserializer)?;
57        let uuid = Uuid::parse_str(&value).map_err(serde::de::Error::custom)?;
58        Ok(Self { uuid })
59    }
60}
61
62impl JsonSchema for ConversationId {
63    fn schema_name() -> Cow<'static, str> {
64        "ConversationId".into()
65    }
66
67    fn json_schema(generator: &mut SchemaGenerator) -> schemars::Schema {
68        <String>::json_schema(generator)
69    }
70}
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75    #[test]
76    fn test_conversation_id_default_is_not_zeroes() {
77        let id = ConversationId::default();
78        assert_ne!(id.uuid, Uuid::nil());
79    }
80}