1 #include "ml_uuid.h"
2 #include "ml_macros.h"
3 
4 typedef struct {
5 	const ml_type_t *Type;
6 	uuid_t Value;
7 } ml_uuid_t;
8 
ml_uuid_hash(ml_uuid_t * UUID,ml_hash_chain_t * Chain)9 static long ml_uuid_hash(ml_uuid_t *UUID, ml_hash_chain_t *Chain) {
10 	return *(long *)UUID->Value;
11 }
12 
13 ML_TYPE(MLUUIDT, (), "uuid",
14 	.hash = (void *)ml_uuid_hash
15 );
16 
ml_uuid(const uuid_t Value)17 ml_value_t *ml_uuid(const uuid_t Value) {
18 	ml_uuid_t *UUID = new(ml_uuid_t);
19 	UUID->Type = MLUUIDT;
20 	uuid_copy(UUID->Value, Value);
21 	return (ml_value_t *)UUID;
22 }
23 
ml_uuid_parse(const char * Value,int Length)24 ml_value_t *ml_uuid_parse(const char *Value, int Length) {
25 	ml_uuid_t *UUID = new(ml_uuid_t);
26 	UUID->Type = MLUUIDT;
27 	if (uuid_parse(Value, UUID->Value)) {
28 		return ml_error("UUIDError", "Invalid UUID string");
29 	}
30 	return (ml_value_t *)UUID;
31 }
32 
ML_METHOD(MLUUIDT)33 ML_METHOD(MLUUIDT) {
34 	ml_uuid_t *UUID = new(ml_uuid_t);
35 	UUID->Type = MLUUIDT;
36 	uuid_generate(UUID->Value);
37 	return (ml_value_t *)UUID;
38 }
39 
ML_METHOD(MLUUIDT,MLStringT)40 ML_METHOD(MLUUIDT, MLStringT) {
41 	return ml_uuid_parse(ml_string_value(Args[0]), ml_string_length(Args[0]));
42 }
43 
ML_METHOD(MLStringT,MLUUIDT)44 ML_METHOD(MLStringT, MLUUIDT) {
45 	ml_uuid_t *UUID = (ml_uuid_t *)Args[0];
46 	char *String = snew(UUID_STR_LEN);
47 	uuid_unparse_lower(UUID->Value, String);
48 	return ml_string(String, UUID_STR_LEN - 1);
49 }
50 
51 ML_METHOD("append", MLStringBufferT, MLUUIDT) {
52 	ml_stringbuffer_t *Buffer = (ml_stringbuffer_t *)Args[0];
53 	ml_uuid_t *UUID = (ml_uuid_t *)Args[1];
54 	char String[UUID_STR_LEN];
55 	uuid_unparse_lower(UUID->Value, String);
56 	ml_stringbuffer_add(Buffer, String, UUID_STR_LEN - 1);
57 	return Args[0];
58 }
59 
60 ML_METHOD("<>", MLUUIDT, MLUUIDT) {
61 	ml_uuid_t *UUIDA = (ml_uuid_t *)Args[0];
62 	ml_uuid_t *UUIDB = (ml_uuid_t *)Args[1];
63 	return ml_integer(uuid_compare(UUIDA->Value, UUIDB->Value));
64 }
65 
66 #define ml_comp_method_time_time(NAME, SYMBOL) \
67 	ML_METHOD(NAME, MLUUIDT, MLUUIDT) { \
68 		ml_uuid_t *UUIDA = (ml_uuid_t *)Args[0]; \
69 		ml_uuid_t *UUIDB = (ml_uuid_t *)Args[1]; \
70 		return uuid_compare(UUIDA->Value, UUIDB->Value) SYMBOL 0 ? Args[1] : MLNil; \
71 	}
72 
73 ml_comp_method_time_time("=", ==);
74 ml_comp_method_time_time("!=", !=);
75 ml_comp_method_time_time("<", <);
76 ml_comp_method_time_time(">", >);
77 ml_comp_method_time_time("<=", <=);
78 ml_comp_method_time_time(">=", >=);
79 
80 #ifdef ML_CBOR
81 
82 #include "ml_cbor.h"
83 
ML_TYPED_FN(ml_cbor_write,MLUUIDT,ml_uuid_t * UUID,void * Data,ml_cbor_write_fn WriteFn)84 static ml_value_t *ML_TYPED_FN(ml_cbor_write, MLUUIDT, ml_uuid_t *UUID, void *Data, ml_cbor_write_fn WriteFn) {
85 	ml_cbor_write_tag(Data, WriteFn, 37);
86 	ml_cbor_write_bytes(Data, WriteFn, 16);
87 	WriteFn(Data, UUID->Value, 16);
88 	return NULL;
89 }
90 
ml_cbor_read_uuid_fn(void * Data,int Count,ml_value_t ** Args)91 static ml_value_t *ml_cbor_read_uuid_fn(void *Data, int Count, ml_value_t **Args) {
92 	ML_CHECK_ARG_TYPE(0, MLStringT);
93 	if (ml_string_length(Args[0]) != 16) return ml_error("TagError", "UUID requires 16 bytes");
94 	return ml_uuid((unsigned char *)ml_string_value(Args[0]));
95 }
96 
97 #endif
98 
ml_uuid_init(stringmap_t * Globals)99 void ml_uuid_init(stringmap_t *Globals) {
100 #include "ml_uuid_init.c"
101 	if (Globals) stringmap_insert(Globals, "uuid", MLUUIDT);
102 	ml_string_fn_register("U", ml_uuid_parse);
103 #ifdef ML_CBOR
104 	ml_cbor_default_tag(37, NULL, ml_cbor_read_uuid_fn);
105 #endif
106 }
107