1use brokapi_core::{Charset, CidCaps, CidCodec, CidError, ClientOrderId, NativeCid};
5use uuid::Uuid;
6
7#[derive(Debug, Clone, Copy, Default)]
11pub struct AlorCidCodec;
12
13impl CidCodec for AlorCidCodec {
14 fn caps(&self) -> CidCaps {
15 CidCaps {
16 max_len: 36,
17 charset: Charset::Ascii,
18 native_bits: 128,
19 lossless: true,
20 }
21 }
22
23 fn encode(&self, cid: ClientOrderId) -> Result<NativeCid, CidError> {
24 let s = cid.hyphenated().to_string();
25 if s.len() > self.caps().max_len {
26 return Err(CidError::TooLong {
27 len: s.len(),
28 max: self.caps().max_len,
29 });
30 }
31 Ok(NativeCid::new(s))
32 }
33
34 fn decode(&self, native: &NativeCid) -> Option<ClientOrderId> {
35 Uuid::parse_str(native.as_str()).ok()
36 }
37}
38
39pub fn cid_from_comment(comment: Option<&str>) -> Option<ClientOrderId> {
41 Uuid::parse_str(comment?.trim()).ok()
42}
43
44const FOREIGN_NS: Uuid = Uuid::from_u128(0x7bc5_2f01_53a4_4d0e_9b6a_0c8e_a102_0001);
46
47pub fn foreign_cid(order_id: &str) -> ClientOrderId {
50 Uuid::new_v5(&FOREIGN_NS, order_id.as_bytes())
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56 use proptest::prelude::*;
57
58 #[test]
59 fn foreign_cids_are_stable_and_distinct() {
60 assert_eq!(foreign_cid("18995978560"), foreign_cid("18995978560"));
61 assert_ne!(foreign_cid("18995978560"), foreign_cid("18995978561"));
62 assert_eq!(foreign_cid("x").get_version_num(), 5);
63 }
64
65 #[test]
66 fn only_a_whole_uuid_in_the_comment_is_a_cid() {
67 let cid = Uuid::new_v4();
68 assert_eq!(cid_from_comment(Some(&cid.to_string())), Some(cid));
69 assert_eq!(cid_from_comment(Some("my first order")), None);
70 assert_eq!(cid_from_comment(None), None);
71 }
72
73 proptest! {
74 #[test]
75 fn alor_cid_roundtrip(bytes in any::<[u8; 16]>()) {
76 let cid = ClientOrderId::from_bytes(bytes);
77 let native = AlorCidCodec.encode(cid).expect("encode");
78 prop_assert_eq!(AlorCidCodec.decode(&native), Some(cid));
79 }
80 }
81}